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

feat: add ability to localize common characters #208

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

dlockhart
Copy link
Member

@dlockhart dlockhart commented Nov 8, 2024

I had some trouble figuring out how best to integrate this, so definitely interested in feedback and other ideas.

The big downside to this approach is that every component that wires up to a localizer via the LocalizeMixin is going to have these "common" terms merged into their collection. That's why I needed to use the intl-common prefix on all their keys to avoid a potential collission.

It also means that the common terms will always be fetched once on every page, even if they're not used. Both localize and localizeHTML are synchronous, so I couldn't think of a way to defer the loading of the common stuff. That's no longer true now that loadCommon: true must be set in the config.

lang/en.js Outdated Show resolved Hide resolved
@dlockhart dlockhart force-pushed the GAUD-7171/localize-common-characters branch from ed36b4d to 5c5d537 Compare November 8, 2024 20:53
@dbatiste
Copy link
Contributor

dbatiste commented Nov 8, 2024

The big downside to this approach is that every component that wires up to a localizer via the LocalizeMixin is going to have these "common" terms merged into their collection. That's why I needed to use the intl-common prefix on all their keys to avoid a potential collission.

If more than one collection is fetched, does that mean they are effectively multiple copies of it in memory? It's probably not going to be a huge set, but doesn't seem ideal. Maybe there is a way to share one set? Or, maybe there could be a way for those components to indicate whether to include the common terms in the set? I'm not too familiar with how the terms are fetched, so maybe none of those things are possible.

It also means that the common terms will always be fetched once on every page, even if they're not used. Both localize and localizeHTML are synchronous, so I couldn't think of a way to defer the loading of the common stuff.

I think async localize could potentially complicate things quite a bit for consumers.

lib/localize.js Outdated Show resolved Hide resolved
@@ -164,8 +191,15 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e
}
if (Object.prototype.hasOwnProperty.call(this, 'getLocalizeResources') || Object.prototype.hasOwnProperty.call(this, 'resources')) {
const possibleLanguages = this._generatePossibleLanguages(config);
const resourcesPromise = this.getLocalizeResources(possibleLanguages, config);
resourcesLoadedPromises.push(resourcesPromise);
if (config?.importFunc) {
Copy link
Member Author

Choose a reason for hiding this comment

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

I had to add this check to handle the case where the consumer only wants to use the common resources.

const resourcesPromise = this.getLocalizeResources(possibleLanguages, config);
resourcesLoadedPromises.push(resourcesPromise);
}
if (config?.loadCommon) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is now only loading the common resources if the consumer explicitly asks for it.

@bearfriend
Copy link
Contributor

If more than one collection is fetched, does that mean they are effectively multiple copies of it in memory?

I think that might be true currently, but we should be able to shift things around a bit to avoid that. The set might actually grow quite a bit so we should be sure about that.

Otherwise this all looks really good to me.

importFunc: async(lang) => {
if (commonResources.has(lang)) return commonResources.get(lang);
const resources = (await import(`../lang/${lang}.js`)).default;
commonResourcesImportCount++;
Copy link
Member Author

Choose a reason for hiding this comment

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

This now keeps a local cache of the common resources, which prevents multiple in-memory copies of the same resources for a given language.

Testing that this was actually working was tricky since we can't observe whether a dynamic import happens or not. I went with a simple counter, which is maybe a bit fragile but gets the job done.

Copy link
Contributor

@bearfriend bearfriend Nov 11, 2024

Choose a reason for hiding this comment

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

This is good for now, I think, but the problem is that we make copies of everything by combining them into a single object per-element, which is bad. We should make a separate story to address this before we expand the list of common messages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants