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

Feature request: allow sharing messages and terms between bundles #503

Closed
Demivan opened this issue Jul 11, 2020 · 9 comments
Closed

Feature request: allow sharing messages and terms between bundles #503

Demivan opened this issue Jul 11, 2020 · 9 comments

Comments

@Demivan
Copy link
Contributor

Demivan commented Jul 11, 2020

I'm working on Vue.js library for fluent.js and wanted to add functionality to split localization into multiple bundles. But I want to be able to share commonly used messages and terms across bundles. Here is simple implementation of a bundle that has this functionality:
https://github.com/Demivan/fluent-vue/blob/7cdd3932130a76b7b270c1113860fb3a3fc8c30f/packages/fluent-vue/src/extendedFluentBundle.ts
This is pretty mush all of it:

getMessage(id: string): Message | undefined {
  return this._messages.get(id) || this.parent.getMessage(id)
}

Problem with it is that child bundle cannot reference parent terms or messages because resolver does not call getMessage method but is accessing _messages directly:

const message = scope.bundle._messages.get(name);

Can something like this e07d6f7 be added so it is possible to implement this functionality?
Or maybe there is other way of sharing messages and terms?

@macabeus
Copy link
Contributor

macabeus commented Jul 12, 2020

Problem with it is that child bundle cannot reference parent terms or messages

I'm sorry, but I can't understand very well the problem that you said here.

I tried the following code:

const resourceCommon = new FluentResource(`
-foo = Foo Term
common = Common Message`)

const resourceMain = new FluentResource(`
test = Test { common } { -foo }`)

const bundle = new FluentBundle('lng')
bundle.addResource(resourceCommon)
bundle.addResource(resourceMain)

const testMessage = bundle.getMessage('test')
const testText = bundle.formatPattern(testMessage.value)
console.log(testText) // Test ⁨Common Message⁩ ⁨Foo Term

That is, on the child bundle I can get the terms and messages from the parent.

Do you want to do something different?

@Demivan
Copy link
Contributor Author

Demivan commented Jul 12, 2020

I have considered doing it this way. Downside of this approach is that changes to parent bundle changes are not reflected in child bundles as messages are just copied.
Maybe that's fine, bundles shouldn't really change.

@Demivan
Copy link
Contributor Author

Demivan commented Jul 15, 2020

Going to close this. Copying messages and terms works

@Demivan Demivan closed this as completed Jul 15, 2020
@stasm
Copy link
Contributor

stasm commented Jul 15, 2020

Sorry I didn't comment earlier. I'd prefer to avoid allowing parent-child hierarchies of bundles. While bundles are mono-lingual, two bundles may be in different languages, have different constructor options (e.g. custom functions or useIsolating), and they cache their own Intl formatters too.

Since messages can reference other messages (and terms), formatPattern does cycle detection to prevent unresolvable cyclic reference. While the current detection would probably work in a scenario where bundles can have parents, the concept of a messgae reference would also become more complex.

That said, I think it might be a good idea to consider a different lookup model than the current one. Perhaps rather than copying messages into the bundle, we could store references to FluentResources and iterate over them in getMessage? @Pike Do you have an opinion about this?

@Demivan
Copy link
Contributor Author

Demivan commented Jul 15, 2020

By the way, why Intl formatters are cached inside a bundle? From what I can see they don't depend on bundle itself, only on its locale. I'm creating a lot of bundles with same locale and cache could be shared between them.

@Pike
Copy link
Contributor

Pike commented Jul 15, 2020

My thinking is based on my writings in https://discourse.mozilla.org/t/on-message-and-termreferences/53217 and https://discourse.mozilla.org/t/semantics-of-bundles-fallbacks/63107.

I'd like for us to fix the problems around language fallbacks, and references with fallbacks. The longer I think about possible solutions, the less the current concept of Bundle helps, and the more I see the localization class concept move to the forefront.

Localization would be a cross-language cross-source concept, and language annotations for formatting and selectors would move to entries or patterns.

The questions we had about currency formatting in the case of falling back among English locales also makes me wonder if we should actually use the current bundle locale list for formatting, or the full language fallback list.

@stasm
Copy link
Contributor

stasm commented Jul 15, 2020

By the way, why Intl formatters are cached inside a bundle? From what I can see they don't depend on bundle itself, only on its locale. I'm creating a lot of bundles with same locale and cache could be shared between them.

That's #218. We've never had a strong use-case for it and most JS apps we've seen don't create more bundles than just a few. I'm happy to revisit it :)

@Demivan
Copy link
Contributor Author

Demivan commented Jul 16, 2020

Global, per locale cache instead of per bundle cache would be really nice to have. Can I create pull request that implements it?

@zanona
Copy link

zanona commented Oct 3, 2020

I am doing some testing having a template en bundle, and a localized one, zh-CN
on my template bundle, I have:

# /locales/en/products.ftl
-product-color--11ae039e = Tangerine
product-3050-20-color = { -product-color--11ae039e }

on the localized one

# locales/zh-CN/products.ftl
-product-color--11ae039e = 柑橘

So I'd think that <Localized id='product-3050-20-color'/> with locale set to zh-CN would return the localized string 柑橘, but it's in fact returning the original string from the template Tangerine.

I am not completely sure this relates to this issue but I'd expect that by just replacing the term on the localized version would be enough to update the message itself? Or perhaps I'm missing something?

The translation was generated from Pontoon, which does not add the affected message which uses the term to the commit.

So in this case, the workaround was re-declaring the message as below. The only issue is that this could become a bit difficult to maintain.

# locales/zh-CN/products.ftl
-product-color--11ae039e = 柑橘
product-3050-20-color = { -product-color--11ae039e }

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

No branches or pull requests

5 participants