2024-10-21 17:21:58 -06:00
|
|
|
// A string localized into multiple locales.
|
|
|
|
export type string = [](locale, str);
|
|
|
|
|
2024-10-21 19:13:49 -06:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// The matching is done as follows. If LC_MESSAGES is of the form
|
|
|
|
// lang_COUNTRY.ENCODING@MODIFIER, then it will match a key of the form
|
|
|
|
// lang_COUNTRY@MODIFIER. If such a key does not exist, it will attempt to match
|
|
|
|
// lang_COUNTRY followed by lang@MODIFIER. Then, a match against lang by itself
|
|
|
|
// will be attempted. Finally, if no matching key is found the required key
|
|
|
|
// without a locale specified is used. The encoding from the LC_MESSAGES value
|
|
|
|
// is ignored when matching.
|
|
|
|
//
|
|
|
|
// If LC_MESSAGES does not have a MODIFIER field, then no key with a modifier
|
|
|
|
// will be matched. Similarly, if LC_MESSAGES does not have a COUNTRY field,
|
|
|
|
// then no key with a country specified will be matched. If LC_MESSAGES just has
|
|
|
|
// a lang field, then it will do a straight match to a key with a similar value.
|
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
|
2024-10-21 17:21:58 -06:00
|
|
|
// Selects the most appropriate localized version of a [[string]] given a
|
2024-10-22 15:23:50 -06:00
|
|
|
// [[locale]]. First, a match against the exact locale is attempted. If nothing
|
|
|
|
// is found, the matching algorithm specified by the XDG Desktop Entry
|
|
|
|
// Specification §5 is used. If nothing is found, an exact match with the C
|
|
|
|
// locale will be attempted. If nothing is found, void will be returned. Memory
|
|
|
|
// is borrowed from the input.
|
2024-10-22 15:21:02 -06:00
|
|
|
export fn string_resolve(strin: string, local: locale) (str | void) = {
|
|
|
|
// lang_COUNTRY@MODIFIER.ENCODING
|
|
|
|
match (string_resolve_exact(strin, local)) {
|
|
|
|
case let result: str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
2024-10-21 18:00:24 -06:00
|
|
|
// lang_COUNTRY@MODIFIER
|
2024-10-21 17:21:58 -06:00
|
|
|
let lang_country_modifier = local;
|
|
|
|
lang_country_modifier.encoding = "";
|
|
|
|
match (string_resolve_exact(strin, lang_country_modifier)) {
|
2024-10-21 18:00:24 -06:00
|
|
|
case let result: str => return result;
|
2024-10-21 17:21:58 -06:00
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
2024-10-21 18:00:24 -06:00
|
|
|
// lang_COUNTRY
|
2024-10-21 17:21:58 -06:00
|
|
|
let lang_country = local;
|
|
|
|
lang_country.modifier = "";
|
|
|
|
match (string_resolve_exact(strin, lang_country)) {
|
2024-10-21 18:00:24 -06:00
|
|
|
case let result: str => return result;
|
2024-10-21 17:21:58 -06:00
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
2024-10-21 18:00:24 -06:00
|
|
|
// lang@MODIFIER
|
2024-10-21 17:21:58 -06:00
|
|
|
let lang_modifier = lang_country_modifier;
|
|
|
|
lang_modifier.country = "";
|
|
|
|
match (string_resolve_exact(strin, lang_modifier)) {
|
2024-10-21 18:00:24 -06:00
|
|
|
case let result: str => return result;
|
2024-10-21 17:21:58 -06:00
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
2024-10-21 18:00:24 -06:00
|
|
|
// lang
|
2024-10-21 17:21:58 -06:00
|
|
|
let lang = lang_modifier;
|
|
|
|
lang.modifier = "";
|
|
|
|
match (string_resolve_exact(strin, lang)) {
|
2024-10-21 18:00:24 -06:00
|
|
|
case let result: str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
// fallback to c locale
|
|
|
|
match (string_resolve_exact(strin, c)) {
|
|
|
|
case let result: str => return result;
|
2024-10-21 17:21:58 -06:00
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
return void;
|
|
|
|
};
|
|
|
|
|
2024-10-21 18:00:24 -06:00
|
|
|
fn string_resolve_exact(strin: string, local: locale) (str | void) = {
|
|
|
|
for (let pair .. strin) if(equal(pair.0, local)) return pair.1;
|
2024-10-21 17:21:58 -06:00
|
|
|
};
|
2024-10-21 19:13:49 -06:00
|
|
|
|
|
|
|
// A list of strings localized into multiple locales.
|
|
|
|
export type strings = [](locale, []str);
|
|
|
|
|
|
|
|
// Selects the most appropriate localized version of a [[string]] given a
|
|
|
|
// [[locale]]. See the documentation for [[string_resolve]] for more
|
|
|
|
// information.
|
|
|
|
export fn strings_resolve(strins: strings, local: locale) ([]str | void) = {
|
2024-10-22 15:21:02 -06:00
|
|
|
// lang_COUNTRY@MODIFIER.ENCODING
|
|
|
|
match (strings_resolve_exact(strins, local)) {
|
|
|
|
case let result: []str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
2024-10-21 19:13:49 -06:00
|
|
|
// lang_COUNTRY@MODIFIER
|
|
|
|
let lang_country_modifier = local;
|
|
|
|
lang_country_modifier.encoding = "";
|
|
|
|
match (strings_resolve_exact(strins, lang_country_modifier)) {
|
|
|
|
case let result: []str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
// lang_COUNTRY
|
|
|
|
let lang_country = local;
|
|
|
|
lang_country.modifier = "";
|
|
|
|
match (strings_resolve_exact(strins, lang_country)) {
|
|
|
|
case let result: []str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
// lang@MODIFIER
|
|
|
|
let lang_modifier = lang_country_modifier;
|
|
|
|
lang_modifier.country = "";
|
|
|
|
match (strings_resolve_exact(strins, lang_modifier)) {
|
|
|
|
case let result: []str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
// lang
|
|
|
|
let lang = lang_modifier;
|
|
|
|
lang.modifier = "";
|
|
|
|
match (strings_resolve_exact(strins, lang)) {
|
|
|
|
case let result: []str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
// fallback to c locale
|
|
|
|
match (strings_resolve_exact(strins, c)) {
|
|
|
|
case let result: []str => return result;
|
|
|
|
case => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
return void;
|
|
|
|
};
|
|
|
|
|
|
|
|
fn strings_resolve_exact(strins: strings, local: locale) ([]str | void) = {
|
|
|
|
for (let pair .. strins) if(equal(pair.0, local)) return pair.1;
|
|
|
|
};
|