import ceylon.collection {

"Localized information about the language associated with 
 the given locale [[tag]]."
shared sealed class Language(tag, 
    languageCode, countryCode, variant, 
    displayLanguage, displayCountry, displayVariant) {
    "The BCP 47 locale tag, for example, `en`, `ca`, `en-AU`, 
     or `es-MX`."
    shared String tag;

    "The language code, for example, `en`, or `es`."
    shared String languageCode;
    "The country or region code, for example, `AU`, or `MX`."
    shared String? countryCode;
    "Variant values, separated by underscores."
    shared String? variant;
    "A localized displayable name for this [[tag]], for
     example, `English`, `inglés`, `English (Australia)`, 
     or `inglés (Australia)`."
    shared String displayName;
    "A localized displayable name for the [[languageCode]],
     for example, `English`, or `inglés`."
    shared String displayLanguage;
    "A localized displayable name for the [[countryCode]],
     for example, `Australia`, or `México`."
    shared String? displayCountry;
    "A localized displayable name for the language 
    shared String? displayVariant;

[Language,String?] parseLanguage(Iterator<String> lines, String tag) {
    assert (!is Finished firstLine =;
    value cols = columns(firstLine).iterator();
    assert (is String loc =, loc==tag);
    assert (is String languageCode =;
    assert (is String? countryCode =;
    assert (is String? variant =;
    assert (is String displayName =;
    assert (is String displayLanguage =;
    assert (is String? displayCountry =;
    assert (is String? displayVariant =;
    assert (is String? currencyCode =;
    value language = Language {
        tag = tag;
        languageCode = languageCode;
        countryCode = countryCode;
        variant = variant;
        displayName = displayName;
        displayLanguage = displayLanguage;
        displayCountry = displayCountry;
        displayVariant = displayVariant;
    return [language, currencyCode];

HashMap<Character,String> parseCaseMappings(Iterator<String> lines) {
    value caseMappings = HashMap<Character,String>();
    if (!is Finished line =, !line.empty) {
        for (col in columns(line)) {
            assert (exists col, exists ch = col[0]);
            caseMappings[ch] = col[2...];
    return caseMappings;

HashMap<String,Language> parseLanguages(Iterator<String> lines) {
    value languages = HashMap<String,Language>();
    while (!is Finished langLine =, 
           !langLine.empty) {
        value langCols = columns(langLine).iterator();
        assert (is String langTag =;
        assert (is String langLanguageCode =;
        assert (is String? langCountryCode =;
        assert (is String? langVariant =;
        assert (is String langDisplayName =;
        assert (is String langDisplayLanguage =;
        assert (is String? langDisplayCountry =;
        assert (is String? langDisplayVariant =;
            = Language {
                tag = langTag;
                languageCode = langLanguageCode;
                countryCode = langCountryCode;
                variant = langVariant;
                displayName = langDisplayName;
                displayLanguage = langDisplayLanguage;
                displayCountry = langDisplayCountry;
                displayVariant = langDisplayVariant;
    return languages;