// A string localized into multiple locales. export type string = [](locale, str); // -------------------------------------------------------------------------- // // 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. // -------------------------------------------------------------------------- // // Selects the most appropriate localized version of a [[string]] given a // [[locale]]. The matching algorithm used is the one specified by the // XDG Desktop Entry Specification, ยง5, with the addition of a preliminary step // where a match against the exact locale is attempted. If no suitable version // is found, an exact match with the C locale will be attempted. If there are // none, void will be returned. Memory is borrowed from the input. 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; }; // lang_COUNTRY@MODIFIER let lang_country_modifier = local; lang_country_modifier.encoding = ""; match (string_resolve_exact(strin, lang_country_modifier)) { case let result: str => return result; case => void; }; // lang_COUNTRY let lang_country = local; lang_country.modifier = ""; match (string_resolve_exact(strin, lang_country)) { case let result: str => return result; case => void; }; // lang@MODIFIER let lang_modifier = lang_country_modifier; lang_modifier.country = ""; match (string_resolve_exact(strin, lang_modifier)) { case let result: str => return result; case => void; }; // lang let lang = lang_modifier; lang.modifier = ""; match (string_resolve_exact(strin, lang)) { case let result: str => return result; case => void; }; // fallback to c locale match (string_resolve_exact(strin, c)) { case let result: str => return result; case => void; }; return void; }; fn string_resolve_exact(strin: string, local: locale) (str | void) = { for (let pair .. strin) if(equal(pair.0, local)) return pair.1; }; // 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) = { // lang_COUNTRY@MODIFIER.ENCODING match (strings_resolve_exact(strins, local)) { case let result: []str => return result; case => void; }; // 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; };