Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[i18n] Load "en" translations parallely #3102

Merged
merged 19 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b0ab693
load en translations in parallel
rajatvijay Jul 27, 2023
855da7b
Merge branch 'develop' of github.com:centerofci/mathesar into i18n-lo…
rajatvijay Sep 6, 2023
1738aca
renamed loadTranslationsIntoMemory to loadTranslations
rajatvijay Sep 6, 2023
b5c5bde
made translations script async
rajatvijay Sep 6, 2023
9b1c64c
Merge branch 'develop' into i18n-load-en-translations-parallely
rajatvijay Sep 17, 2023
42830ff
move translations path logic to context processor
rajatvijay Sep 18, 2023
8b22c87
use loadAsyncLocale to let vite bundle it as default exported module
rajatvijay Sep 19, 2023
c5ed4bc
lint fixes
rajatvijay Sep 19, 2023
25c89ce
do not read legacy builds for translations files
rajatvijay Sep 19, 2023
43243d3
Merge branch 'develop' into i18n-load-en-translations-parallely
rajatvijay Sep 19, 2023
737effa
render page when loading default lang translations
rajatvijay Sep 19, 2023
a9235ab
Merge branch 'i18n-load-en-translations-parallely' of github.com:cent…
rajatvijay Sep 19, 2023
01a4b4e
Merge branch 'develop' into i18n-load-en-translations-parallely
pavish Sep 20, 2023
6c5a54d
Merge branch 'develop' of github.com:centerofci/mathesar into i18n-lo…
rajatvijay Sep 22, 2023
2d99656
Merge branch 'develop' of github.com:centerofci/mathesar into i18n-lo…
rajatvijay Oct 9, 2023
b11f2b0
move window.Mathesar.translations init in translations file
rajatvijay Oct 9, 2023
e17a308
removed import with explicit extensions
rajatvijay Oct 9, 2023
6c50c83
moved i18n cache to i18n-store file from utils
rajatvijay Oct 9, 2023
e30a065
read new translations format in App.svelte
rajatvijay Oct 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 35 additions & 2 deletions config/context_processors.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
from django.conf import settings
from django.templatetags.static import static


from mathesar.utils.frontend import get_manifest_data


def frontend_settings(request):
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(),
'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'
else:
try:
module_translations_file_path = static(manifest_data[preferred_language]["file"])
except KeyError:
module_translations_file_path = static(manifest_data[default_language]["file"])

return {
'module_translations_file_path': module_translations_file_path,
'preferred_language': preferred_language
}
7 changes: 7 additions & 0 deletions config/settings/common_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -250,3 +251,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')),
]
23 changes: 18 additions & 5 deletions mathesar/templates/mathesar/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
{% block title %}Home{% endblock %}

{% block styles %}
{% if not development_mode %} {% for css_file in manifest_data.module_css %}
<link rel="stylesheet" href="{% static css_file %}" />
{% endfor %} {% endif %}
{% if not development_mode %}
{% for css_file in manifest_data.module_css %}
<link rel="stylesheet" href="{% static css_file %}" />
{% endfor %}
{% endif %}
{% endblock %}

{% block scripts %}
Expand All @@ -17,6 +19,16 @@
{% endfor %}
{% endif %}

<script type="module">
import("{{ module_translations_file_path }}").then(translations => {
window.mathesar = window.mathesar || {};
window.mathesar.translations = {
lang: "{{ preferred_language }}",
translationStrings: JSON.stringify(translations.default)
};
})
</script>

{% if development_mode %}
<script type="module" src="{{ client_dev_url }}/@vite/client"></script>
<script type="module" src="{{ client_dev_url }}/src/main.ts"></script>
Expand Down Expand Up @@ -52,12 +64,13 @@
></script>
<script
nomodule
id="vite-legacy-entry"
id="vite-legacy-js-slot"
data-src="{% static manifest_data.legacy_js %}"
>
System.import(
document.getElementById("vite-legacy-entry").getAttribute("data-src")
document.getElementById("vite-legacy-js-slot").getAttribute("data-src")
);
</script>

{% endif %}
{% endblock %}
4 changes: 3 additions & 1 deletion mathesar/utils/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ def get_manifest_data():
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']

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']

for locale, _ in settings.LANGUAGES or []:
manifest_data[locale] = raw_data[f'src/i18n/{locale}/index.ts']

# Cache data for 1 hour
cache.set('manifest_data', manifest_data, 60 * 60)
return manifest_data
45 changes: 29 additions & 16 deletions mathesar_ui/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,51 @@
import { preloadCommonData } from '@mathesar/utils/preloadData';
import AppContext from './AppContext.svelte';
import RootRoute from './routes/RootRoute.svelte';
import { loadLocaleAsync } from './i18n/i18n-load';
import { setLocale } from './i18n/i18n-svelte';
import type { RequestStatus } from './api/utils/requestUtils';
import { getErrorMessage } from './utils/errors';
import ErrorBox from './components/message-boxes/ErrorBox.svelte';
import { loadLocaleAsync, loadTranslations } from './i18n/i18n-load';

let isTranslationsLoaded = false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from @seancolsen - adding a comment here explaining "why this approach?" since this approach is weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

/**
* Later the translations file will be loaded
* in parallel to the FE's first chunk
* Why translations are being read from window object?
* In order to -
* 1. Load the translations file in parallel to the first FE chunk.
* 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 object which is being read here
*/
let translationLoadStatus: RequestStatus = { state: 'processing' };
void (async () => {
try {
const { translations } = window.mathesar || {};
if (translations) {
loadTranslations(
translations.lang,
JSON.parse(translations.translationStrings),
);
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');
pavish marked this conversation as resolved.
Show resolved Hide resolved
setLocale('en');
translationLoadStatus = { state: 'success' };
} catch (exp) {
translationLoadStatus = {
state: 'failure',
errors: [getErrorMessage(exp)],
};
isTranslationsLoaded = true;
}
})();

const commonData = preloadCommonData();
</script>

{#if translationLoadStatus.state === 'success' && commonData}
{#if isTranslationsLoaded && commonData}
<AppContext {commonData}>
<RootRoute {commonData} />
</AppContext>
{:else if translationLoadStatus.state === 'processing'}
{:else if !isTranslationsLoaded}
<div class="app-loader">
<Spinner size="2rem" />
</div>
Expand Down
8 changes: 8 additions & 0 deletions mathesar_ui/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ declare module '*.mdx' {
const value: string;
export default value;
}

interface Window {
mathesar:
| {
translations: { lang: Locales; translationStrings: string } | undefined;
}
| undefined;
}
5 changes: 5 additions & 0 deletions mathesar_ui/src/i18n/i18n-load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ export async function loadLocaleAsync(locale: Locales): Promise<void> {
updateTranslationsDictionary(locale, await importLocaleAsync(locale));
loadFormatters(locale);
}

export function loadTranslations(locale: Locales, translations: Translations) {
updateTranslationsDictionary(locale, translations);
loadFormatters(locale);
}
6 changes: 5 additions & 1 deletion mathesar_ui/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ export default defineConfig({
build: {
manifest: true,
rollupOptions: {
input: './src/main.ts',
input: {
main: './src/main.ts',
en: './src/i18n/en/index.ts',
ja: './src/i18n/ja/index.ts',
},
},
outDir: '../mathesar/static/mathesar/',
emptyOutDir: true,
Expand Down