From b0ab693c3805009aa5fe1065af71826cb9bec7d2 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 27 Jul 2023 03:43:05 +0000 Subject: [PATCH 01/12] load en translations in parallel --- config/context_processors.py | 9 +++++++- mathesar/templates/mathesar/index.html | 32 ++++++++++++++++++++++---- mathesar/utils/frontend.py | 15 +++++++++++- mathesar_ui/src/App.svelte | 29 ++++++++++++++--------- mathesar_ui/src/i18n/i18n-load.ts | 8 +++++++ 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/config/context_processors.py b/config/context_processors.py index da5e98a752..800fbcc31d 100644 --- a/config/context_processors.py +++ b/config/context_processors.py @@ -4,9 +4,16 @@ def frontend_settings(request): + """ + Hard coding this for now + but will be taken from users model + and cookies later on + """ + preferred_language = 'en' frontend_settings = { 'development_mode': settings.MATHESAR_MODE == 'DEVELOPMENT', - 'manifest_data': get_manifest_data(), + 'manifest_data': get_manifest_data(preferred_language), + 'preferred_language': preferred_language, 'live_demo_mode': getattr(settings, 'MATHESAR_LIVE_DEMO', False), 'live_demo_username': getattr(settings, 'MATHESAR_LIVE_DEMO_USERNAME', None), 'live_demo_password': getattr(settings, 'MATHESAR_LIVE_DEMO_PASSWORD', None), diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index e26130095d..2d4e616ef6 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -4,9 +4,11 @@ {% block title %}Home{% endblock %} {% block styles %} - {% if not development_mode %} {% for css_file in manifest_data.module_css %} - - {% endfor %} {% endif %} + {% if not development_mode %} + {% for css_file in manifest_data.module_css %} + + {% endfor %} + {% endif %} {% endblock %} {% block scripts %} @@ -17,6 +19,17 @@ {% endfor %} {% endif %} + + {% if development_mode %} @@ -52,11 +65,20 @@ > + {% endif %} diff --git a/mathesar/utils/frontend.py b/mathesar/utils/frontend.py index 428017f7f0..78d7f4433c 100644 --- a/mathesar/utils/frontend.py +++ b/mathesar/utils/frontend.py @@ -4,7 +4,7 @@ from django.core.cache import cache -def get_manifest_data(): +def get_manifest_data(preferred_language): # We don't need the manifest data for local development. if settings.MATHESAR_MODE == 'DEVELOPMENT': return {} @@ -18,14 +18,27 @@ def get_manifest_data(): with open(settings.MATHESAR_MANIFEST_LOCATION, 'r') as manifest_file: raw_data = json.loads(manifest_file.read()) + translations_file_path = get_translations_file_path(preferred_language) + module_data = raw_data['src/main.ts'] manifest_data['module_css'] = [filename for filename in module_data['css']] manifest_data['module_js'] = module_data['file'] + # Purposefully letting it fail if the translations file for that lang is not in the bundle + manifest_data['module_translations_file'] = raw_data[translations_file_path["module"]]["file"] + legacy_data = raw_data['src/main-legacy.ts'] manifest_data['legacy_polyfill_js'] = raw_data['vite/legacy-polyfills-legacy']['file'] manifest_data['legacy_js'] = legacy_data['file'] + manifest_data['legacy_translations_file'] = raw_data[translations_file_path["legacy"]]["file"] # Cache data for 1 hour cache.set('manifest_data', manifest_data, 60 * 60) return manifest_data + + +def get_translations_file_path(preferred_language): + return { + "module": f'src/i18n/{preferred_language}/index.ts', + "legacy": f'src/i18n/{preferred_language}/index-legacy.ts' + } diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 398725674e..1c7fb53f6e 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -19,21 +19,28 @@ import { modal } from './stores/modal'; import { setReleasesStoreInContext } from './stores/releases'; import ModalRecordSelector from './systems/record-selector/ModalRecordSelector.svelte'; - import { loadLocaleAsync } from './i18n/i18n-load'; import { setLocale } from './i18n/i18n-svelte'; + import type { Locales } from './i18n/i18n-types'; + import { loadTranslationsIntoMemory } from './i18n/i18n-load'; - /** - * Later the translations file will be loaded - * in parallel to the FE's first chunk - */ let isTranslationsLoaded = false; - (() => { - void loadLocaleAsync('en').then(() => { - setLocale('en'); + const checkTranslationsInterval = setInterval(() => { + // eslint-disable-next-line prefer-destructuring + const translations: + | { lang: Locales; translationStrings: string } + | undefined = + // @ts-expect-error added by index.html + window.translations; + if (translations) { + loadTranslationsIntoMemory( + translations.lang, + JSON.parse(translations.translationStrings), + ); + setLocale(translations.lang); isTranslationsLoaded = true; - return true; - }); - })(); + clearInterval(checkTranslationsInterval); + } + }, 100); const commonData = preloadCommonData(); if (commonData?.user) { diff --git a/mathesar_ui/src/i18n/i18n-load.ts b/mathesar_ui/src/i18n/i18n-load.ts index 02f828295e..6e0aabee3b 100644 --- a/mathesar_ui/src/i18n/i18n-load.ts +++ b/mathesar_ui/src/i18n/i18n-load.ts @@ -30,3 +30,11 @@ export async function loadLocaleAsync(locale: Locales): Promise { updateTranslationsDictionary(locale, await importLocaleAsync(locale)); loadFormatters(locale); } + +export function loadTranslationsIntoMemory( + locale: Locales, + translations: Translations, +) { + updateTranslationsDictionary(locale, translations); + loadFormatters(locale); +} From 1738aca591db359496eca1185bffb369b08cb7e4 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Wed, 6 Sep 2023 15:16:17 +0530 Subject: [PATCH 02/12] renamed loadTranslationsIntoMemory to loadTranslations --- mathesar_ui/src/App.svelte | 4 ++-- mathesar_ui/src/i18n/i18n-load.ts | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 391414ef5b..ed1e4d2517 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -5,13 +5,13 @@ import RootRoute from './routes/RootRoute.svelte'; import { setLocale } from './i18n/i18n-svelte'; import ErrorBox from './components/message-boxes/ErrorBox.svelte'; - import { loadTranslationsIntoMemory } from './i18n/i18n-load'; + import { loadTranslations } from './i18n/i18n-load'; let isTranslationsLoaded = false; const checkTranslationsAvailableInterval = setInterval(() => { const { translations } = window; if (translations) { - loadTranslationsIntoMemory( + loadTranslations( translations.lang, JSON.parse(translations.translationStrings), ); diff --git a/mathesar_ui/src/i18n/i18n-load.ts b/mathesar_ui/src/i18n/i18n-load.ts index 6e0aabee3b..975abf24f7 100644 --- a/mathesar_ui/src/i18n/i18n-load.ts +++ b/mathesar_ui/src/i18n/i18n-load.ts @@ -31,10 +31,7 @@ export async function loadLocaleAsync(locale: Locales): Promise { loadFormatters(locale); } -export function loadTranslationsIntoMemory( - locale: Locales, - translations: Translations, -) { +export function loadTranslations(locale: Locales, translations: Translations) { updateTranslationsDictionary(locale, translations); loadFormatters(locale); } From b5c5bde9ab57d42a5b0f1ec9be271558013d5477 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Wed, 6 Sep 2023 16:13:47 +0530 Subject: [PATCH 03/12] made translations script async --- mathesar/templates/mathesar/index.html | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index 2d4e616ef6..fd95be1b96 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -19,8 +19,9 @@ {% endfor %} {% endif %} - + {% endif %} {% endblock %} From 42830ffc3d1a43cbfd50809bfe5d6cad505bd222 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Mon, 18 Sep 2023 09:40:56 +0000 Subject: [PATCH 04/12] move translations path logic to context processor --- config/context_processors.py | 48 +++++++++++++++++++++----- config/settings/common_settings.py | 7 ++++ mathesar/templates/mathesar/index.html | 6 ++-- mathesar/utils/frontend.py | 20 +++-------- mathesar_ui/vite.config.js | 6 +++- 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/config/context_processors.py b/config/context_processors.py index 800fbcc31d..c60c25de78 100644 --- a/config/context_processors.py +++ b/config/context_processors.py @@ -1,24 +1,54 @@ from django.conf import settings +from django.templatetags.static import static + from mathesar.utils.frontend import get_manifest_data def frontend_settings(request): - """ - Hard coding this for now - but will be taken from users model - and cookies later on - """ - preferred_language = 'en' + manifest_data = get_manifest_data() + development_mode = settings.MATHESAR_MODE == 'DEVELOPMENT' + + i18n_settings = get_i18n_settings(manifest_data, development_mode) frontend_settings = { - 'development_mode': settings.MATHESAR_MODE == 'DEVELOPMENT', - 'manifest_data': get_manifest_data(preferred_language), - 'preferred_language': preferred_language, + 'development_mode': development_mode, + 'manifest_data': manifest_data, 'live_demo_mode': getattr(settings, 'MATHESAR_LIVE_DEMO', False), 'live_demo_username': getattr(settings, 'MATHESAR_LIVE_DEMO_USERNAME', None), 'live_demo_password': getattr(settings, 'MATHESAR_LIVE_DEMO_PASSWORD', None), + **i18n_settings } # Only include development URL if we're in development mode. if frontend_settings['development_mode'] is True: frontend_settings['client_dev_url'] = settings.MATHESAR_CLIENT_DEV_URL + return frontend_settings + + +def get_i18n_settings(manifest_data, development_mode): + """ + Hard coding this for now + but will be taken from users model + and cookies later on + """ + preferred_language = 'en' + default_language = 'en' + + client_dev_url = settings.MATHESAR_CLIENT_DEV_URL + + if development_mode is True: + module_translations_file_path = f'{client_dev_url}/src/i18n/{preferred_language}/index.ts' + legacy_translations_file_path = "" + else: + try: + module_translations_file_path = static(manifest_data[preferred_language]["file"]) + legacy_translations_file_path = static(manifest_data[f"{preferred_language}-legacy"]["file"]) + except KeyError: + module_translations_file_path = static(manifest_data[default_language]["file"]) + legacy_translations_file_path = static(manifest_data[f"{default_language}-legacy"]["file"]) + + return { + 'module_translations_file_path': module_translations_file_path, + 'legacy_translations_file_path': legacy_translations_file_path, + 'preferred_language': preferred_language + } diff --git a/config/settings/common_settings.py b/config/settings/common_settings.py index b72d22ddad..5f1dcc9164 100644 --- a/config/settings/common_settings.py +++ b/config/settings/common_settings.py @@ -15,6 +15,7 @@ from decouple import Csv, config as decouple_config from dj_database_url import parse as db_url +from django.utils.translation import gettext_lazy # We use a 'tuple' with pipes as delimiters as decople naively splits the global @@ -248,3 +249,9 @@ def pipe_delim(pipe_string): } # List of Template names that contains additional script tags to be added to the base template BASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = [] + +# i18n +LANGUAGES = [ + ('en', gettext_lazy('English')), + ('ja', gettext_lazy('Japanese')), +] diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index fd95be1b96..25a38afd32 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -21,9 +21,7 @@ {% comment %} Making it async to start the execution as soon as its downloaded without making it wait for the HTML to be parsed {% endcomment %} @@ -62,16 +62,6 @@ nomodule src="{% static manifest_data.legacy_polyfill_js %}" > - diff --git a/mathesar_ui/src/global.d.ts b/mathesar_ui/src/global.d.ts index 41aa976973..dfbdbd61e5 100644 --- a/mathesar_ui/src/global.d.ts +++ b/mathesar_ui/src/global.d.ts @@ -7,5 +7,9 @@ declare module '*.mdx' { } interface Window { - translations: { lang: Locales; translationStrings: string } | undefined; + mathesar: + | { + translations: { lang: Locales; translationStrings: string } | undefined; + } + | undefined; } From c5ed4bcd87dca4c1efe9b235923c933a3884da4f Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 19 Sep 2023 15:48:39 +0530 Subject: [PATCH 06/12] lint fixes --- mathesar_ui/src/App.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 5eac49922f..42108129c6 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -36,7 +36,7 @@ * it as a default exported module. Otherwise vite converts the * default export to named exports internally for the sake of optimization. */ - loadLocaleAsync('en'); + void loadLocaleAsync('en'); } const commonData = preloadCommonData(); From 25c89ce4a16ea2af74322def5f540ca8e8325cd1 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 19 Sep 2023 15:50:02 +0530 Subject: [PATCH 07/12] do not read legacy builds for translations files --- mathesar/utils/frontend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mathesar/utils/frontend.py b/mathesar/utils/frontend.py index 8c0ad8fff4..ca4f3e084d 100644 --- a/mathesar/utils/frontend.py +++ b/mathesar/utils/frontend.py @@ -27,7 +27,6 @@ def get_manifest_data(): for locale, _ in settings.LANGUAGES or []: manifest_data[locale] = raw_data[f'src/i18n/{locale}/index.ts'] - manifest_data[f"{locale}-legacy"] = raw_data[f'src/i18n/{locale}/index-legacy.ts'] # Cache data for 1 hour cache.set('manifest_data', manifest_data, 60 * 60) From 737effa9e60660e58e39c28b60c1bcdbe94de56e Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 19 Sep 2023 16:34:35 +0530 Subject: [PATCH 08/12] render page when loading default lang translations --- mathesar_ui/src/App.svelte | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 42108129c6..d0e4ceb352 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -15,9 +15,9 @@ * 2. And then make it available for the entry(App.svelte) * file to load them into memory. * the index.html loads it as using a script tag and attach it - * to the window's global object which is being read here + * to the window object which is being read here */ - try { + void (async () => { const { translations } = window.mathesar || {}; if (translations) { loadTranslations( @@ -26,18 +26,19 @@ ); setLocale(translations.lang); isTranslationsLoaded = true; + } else { + /** + * !!! CAUTION: DO NOT REMOVE THIS !!! + * Reason: Apart from loading the `en` translations as default + * when there are translations on the window object, + * this also tells the vite bundler to bundle + * it as a default exported module. Otherwise vite converts the + * default export to named exports internally for the sake of optimization. + */ + await loadLocaleAsync('en'); + isTranslationsLoaded = true; } - } catch { - /** - * !!! CAUTION: DO NOT REMOVE THIS !!! - * Reason: Apart from loading the `en` translations as default - * when something fails while reading the window's global - * object, this also tells the vite bundler to bundle - * it as a default exported module. Otherwise vite converts the - * default export to named exports internally for the sake of optimization. - */ - void loadLocaleAsync('en'); - } + })(); const commonData = preloadCommonData(); From b11f2b04a8f161183181b852c20805dfd04f3c46 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Mon, 9 Oct 2023 16:58:39 +0530 Subject: [PATCH 09/12] move window.Mathesar.translations init in translations file --- config/context_processors.py | 4 ++++ mathesar/templates/mathesar/index.html | 19 ++++++++++--------- mathesar/utils/frontend.py | 1 + mathesar_ui/src/global.d.ts | 4 ++-- mathesar_ui/src/i18n/en/index.ts | 5 ++++- mathesar_ui/src/i18n/i18n-util.ts | 14 ++++++++++++++ mathesar_ui/src/i18n/ja/index.ts | 7 ++++++- 7 files changed, 41 insertions(+), 13 deletions(-) diff --git a/config/context_processors.py b/config/context_processors.py index 1c8e00ceae..4906bbf3e4 100644 --- a/config/context_processors.py +++ b/config/context_processors.py @@ -38,13 +38,17 @@ def get_i18n_settings(manifest_data, development_mode): if development_mode is True: module_translations_file_path = f'{client_dev_url}/src/i18n/{preferred_language}/index.ts' + legacy_translations_file_path = f'{client_dev_url}/src/i18n/{preferred_language}/index.ts' else: try: module_translations_file_path = static(manifest_data[preferred_language]["file"]) + legacy_translations_file_path = static(manifest_data[f"{preferred_language}-legacy"]["file"]) except KeyError: module_translations_file_path = static(manifest_data[default_language]["file"]) + legacy_translations_file_path = static(manifest_data[f"{default_language}-legacy"]["file"]) return { 'module_translations_file_path': module_translations_file_path, + 'legacy_translations_file_path': legacy_translations_file_path, 'preferred_language': preferred_language } diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index 0b979b348f..30e8593603 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -19,15 +19,7 @@ {% endfor %} {% endif %} - + {% if development_mode %} @@ -62,6 +54,15 @@ nomodule src="{% static manifest_data.legacy_polyfill_js %}" > +