Skip to content

Commit

Permalink
Merge pull request #1044 from kiwix/default_ui_language_is_resolved_i…
Browse files Browse the repository at this point in the history
…n_the_frontend

Default UI language is resolved in the frontend
  • Loading branch information
mgautierfr authored Jan 31, 2024
2 parents aff801e + c697611 commit 795fcb9
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 161 deletions.
3 changes: 1 addition & 2 deletions src/server/internalServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,7 @@ std::unique_ptr<Response> InternalServer::handle_viewer_settings(const RequestCo
const kainjow::mustache::object data{
{"enable_toolbar", m_withTaskbar ? "true" : "false" },
{"enable_link_blocking", m_blockExternalLinks ? "true" : "false" },
{"enable_library_button", m_withLibraryButton ? "true" : "false" },
{"default_user_language", request.get_user_language() }
{"enable_library_button", m_withLibraryButton ? "true" : "false" }
};
return ContentResponse::build(RESOURCE::templates::viewer_settings_js, data, "application/javascript; charset=utf-8");
}
Expand Down
11 changes: 7 additions & 4 deletions static/generate_i18n_resources_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ def get_translation_info(filepath):
with open(filepath, 'r', encoding="utf-8") as f:
content = json.load(f)
lang_name = content.get("name")
return lang_code, lang_name
translation_count = len(content)
return dict(iso_code=lang_code,
self_name=lang_name,
translation_count=translation_count)

language_list = []
json_files = translation_dir.glob("*.json")
Expand All @@ -40,14 +43,14 @@ def get_translation_info(filepath):
continue
print("Processing", i18n_file.name)
if i18n_file.name != "test.json":
lang_code, lang_name = get_translation_info(i18n_file)
translation_info = get_translation_info(i18n_file)
lang_name = translation_info["self_name"]
if lang_name:
language_list.append((lang_code, lang_name))
language_list.append(translation_info)
else:
print(f"Warning: missing 'name' in {i18n_file.name}")
f.write(str(i18n_file.relative_to(script_path.parent)) + '\n')

language_list = [{name: code} for code, name in sorted(language_list)]
language_list_jsobj_str = json.dumps(language_list,
indent=2,
ensure_ascii=False)
Expand Down
30 changes: 24 additions & 6 deletions static/skin/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,31 @@ const DEFAULT_UI_LANGUAGE = 'en';

Translations.load(DEFAULT_UI_LANGUAGE, /*asDefault=*/true);

// Below function selects the most suitable UI language from the list
// of preferred languages in browser preferences and available translations.
// Since, unlike Accept-Language header, navigator.languages doesn't contain
// qvalues, they are computed using the same algorithm as in Firefox 121
function getDefaultUserLanguage() {
const mostSuitableLang = { code: DEFAULT_UI_LANGUAGE, score: 0 }
const n = navigator.languages.length;
for (const lang of uiLanguages ) {
const rank = navigator.languages.indexOf(lang.iso_code);
if ( rank >= 0 ) {
const qvalue = Math.round(10*(1 - rank/n))/10;
const score = qvalue * lang.translation_count;
if ( score > mostSuitableLang.score ) {
mostSuitableLang.code = lang.iso_code;
mostSuitableLang.score = score;
}
}
}
return mostSuitableLang.code;
}

function getUserLanguage() {
return new URLSearchParams(window.location.search).get('userlang')
|| window.localStorage.getItem('userlang')
|| viewerSettings.defaultUserLanguage
|| DEFAULT_UI_LANGUAGE;
|| getDefaultUserLanguage();
}

function setUserLanguage(lang, callback) {
Expand Down Expand Up @@ -164,10 +184,8 @@ function initUILanguageSelector(activeLanguage, languageChangeCallback) {
}
const languageSelector = document.getElementById("ui_language");
for (const lang of uiLanguages ) {
const lang_name = Object.getOwnPropertyNames(lang)[0];
const lang_code = lang[lang_name];
const is_selected = lang_code == activeLanguage;
languageSelector.appendChild(new Option(lang_name, lang_code, is_selected, is_selected));
const is_selected = lang.iso_code == activeLanguage;
languageSelector.appendChild(new Option(lang.self_name, lang.iso_code, is_selected, is_selected));
}
languageSelector.onchange = languageChangeCallback;
}
Expand Down
136 changes: 102 additions & 34 deletions static/skin/languages.js
Original file line number Diff line number Diff line change
@@ -1,104 +1,172 @@
const uiLanguages = [
{
"الإنجليزية": "ar"
"iso_code": "ar",
"self_name": "الإنجليزية",
"translation_count": 25
},
{
"বাংলা": "bn"
"iso_code": "bn",
"self_name": "বাংলা",
"translation_count": 12
},
{
"Čeština": "cs"
"iso_code": "cs",
"self_name": "Čeština",
"translation_count": 25
},
{
"Deutsch": "de"
"iso_code": "de",
"self_name": "Deutsch",
"translation_count": 49
},
{
"English": "en"
"iso_code": "en",
"self_name": "English",
"translation_count": 53
},
{
"español": "es"
"iso_code": "es",
"self_name": "español",
"translation_count": 48
},
{
"suomi": "fi"
"iso_code": "fi",
"self_name": "suomi",
"translation_count": 22
},
{
"Français": "fr"
"iso_code": "fr",
"self_name": "Français",
"translation_count": 52
},
{
"עברית": "he"
"iso_code": "he",
"self_name": "עברית",
"translation_count": 52
},
{
"हिन्दी": "hi"
"iso_code": "hi",
"self_name": "हिन्दी",
"translation_count": 49
},
{
"Հայերեն": "hy"
"iso_code": "hy",
"self_name": "Հայերեն",
"translation_count": 15
},
{
"interlingua": "ia"
"iso_code": "ia",
"self_name": "interlingua",
"translation_count": 49
},
{
"italiano": "it"
"iso_code": "it",
"self_name": "italiano",
"translation_count": 29
},
{
"日本語": "ja"
"iso_code": "ja",
"self_name": "日本語",
"translation_count": 26
},
{
"한국어": "ko"
"iso_code": "ko",
"self_name": "한국어",
"translation_count": 13
},
{
"kurdî": "ku-latn"
"iso_code": "ku-latn",
"self_name": "kurdî",
"translation_count": 26
},
{
"Lëtzebuergesch": "lb"
"iso_code": "lb",
"self_name": "Lëtzebuergesch",
"translation_count": 22
},
{
"македонски": "mk"
"iso_code": "mk",
"self_name": "македонски",
"translation_count": 52
},
{
"Bahasa Melayu": "ms"
"iso_code": "ms",
"self_name": "Bahasa Melayu",
"translation_count": 14
},
{
"Nederlands": "nl"
"iso_code": "nl",
"self_name": "Nederlands",
"translation_count": 49
},
{
"ߒߞߏ": "nqo"
"iso_code": "nqo",
"self_name": "ߒߞߏ",
"translation_count": 43
},
{
"ଓଡ଼ିଆ": "or"
"iso_code": "or",
"self_name": "ଓଡ଼ିଆ",
"translation_count": 49
},
{
"Polski": "pl"
"iso_code": "pl",
"self_name": "Polski",
"translation_count": 24
},
{
"русский": "ru"
"iso_code": "ru",
"self_name": "русский",
"translation_count": 45
},
{
"Sardu": "sc"
"iso_code": "sc",
"self_name": "Sardu",
"translation_count": 49
},
{
"slovenčina": "sk"
"iso_code": "sk",
"self_name": "slovenčina",
"translation_count": 25
},
{
"سرائیکی": "skr-arab"
"iso_code": "skr-arab",
"self_name": "سرائیکی",
"translation_count": 20
},
{
"slovenščina": "sl"
"iso_code": "sl",
"self_name": "slovenščina",
"translation_count": 52
},
{
"Shqip": "sq"
"iso_code": "sq",
"self_name": "Shqip",
"translation_count": 49
},
{
"Svenska": "sv"
"iso_code": "sv",
"self_name": "Svenska",
"translation_count": 52
},
{
"ఇంగ్లీషు": "te"
"iso_code": "te",
"self_name": "ఇంగ్లీషు",
"translation_count": 49
},
{
"Türkçe": "tr"
"iso_code": "tr",
"self_name": "Türkçe",
"translation_count": 25
},
{
"英语": "zh-hans"
"iso_code": "zh-hans",
"self_name": "英语",
"translation_count": 16
},
{
"繁體中文": "zh-hant"
"iso_code": "zh-hant",
"self_name": "繁體中文",
"translation_count": 52
}
]
3 changes: 1 addition & 2 deletions static/templates/viewer_settings.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const viewerSettings = {
toolbarEnabled: {{enable_toolbar}},
linkBlockingEnabled: {{enable_link_blocking}},
libraryButtonEnabled: {{enable_library_button}},
defaultUserLanguage: "{{default_user_language}}"
libraryButtonEnabled: {{enable_library_button}}
}
Loading

0 comments on commit 795fcb9

Please sign in to comment.