Replies: 2 comments
-
Sorry about that. I guess discussions are disabled by default, even for newer repos. I've enabled them and converted the issue, since I use issues/PRs as a todo list and discussions aren't necessarily actionable items. There are some cool ideas in here. It seems more like namespacing/grouping terms with a bit of type safety rolled in. I don't mean to sound dismissive, but this is a library that directly supports Shoelace, so its scope is tied to my immediate needs there. I don't want to spend my spare time refactoring this utility because I have other priorities I need to focus on. Typed Translations and ArgumentsThat said, the 3.0 release of this utility makes strong typings easier to achieve by extending the import { LocalizeController as DefaultLocalizeController } from '@shoelace-style/localize';
// Extend the default controller with your custom translation
export class LocalizeController extends DefaultLocalizeController<MyTranslation> {}
// Export `registerTranslation` so you can import everything from this file
export { registerTranslation } from '@shoelace-style/localize';
// Define your translation terms here
export interface MyTranslation extends Translation {
myTerm: string;
myOtherTerm: string;
myTermWithArgs: (count: string) => string;
} With this, calls to Merging TranslationsAlso new in 3.0 is the ability to merge translations of the same code, which was proposed in #7. Removed FunctionsThe top level functions I realize this may be an unpopular decision for anyone who may have been using those methods. To be honest, I don't think I ever meant to expose them and I never even used them. This is the reason for the major version bump. If you find the Reactive Controller pattern unacceptable, I would suggest forking 2.x and refactoring it as desired. Right now, I simply don't have the time to develop and maintain features and improvements that other people need for this utility. As it stands, this micro library satisfies all the requirements I have for Shoelace, so I don't see any new features or refactors happening in the immediate future. I will, of course, continue to address bugs as they arise. |
Beta Was this translation helpful? Give feedback.
-
I've deleted (hiding was not possible) my latest comment at is was just "saying thanks" to Cory for the latest changes in @claviska Nevertheless, namespaces are something to consider for 3rd-party component developers. Long story short: The above proposal is too complicated and kinda over the top ... so Cory, if possible please close, hide, delete it or whatever options there are, as there's no need for further discussion here. BTW: Component libraries (including Shoelace) should always (!) export their translation types! |
Beta Was this translation helpful? Give feedback.
-
Localize
already supports making translations type safe, at least up to a certain point.But this might be a bit too cumbersome currently (I guess that's the reason why this feature has not been used in
@shoelace-style/shoelace
).Please let me propose an alternative concept.
The concept could be implemented completely in user land, but if it was part of Localize or Shoelace we would have the same type safety for all (TS implemented) components in the SL universe, which would be a big win IMHO.
Main advantages:
You cannot use any invalid translation keys in
term(...)
andthis.localize.term(...)
, neither in the newly added (see below) functionthis.localize.t(...)
The translation modules (e.g.
file 'de.ts'
) are also completely type safe, you cannot use invalid translation keys. The types of all translation functions will automatically be inferred, independent whether you translate your own terms or terms of third-party SL-based components. You'll normally only need one simple type definition (=>FullTranslation<'someFancyLibrary'>
, see below) to achieve full type safety in the translation files, the rest will be inferred.Uses categories/namespaces for terms, so no name collisions with name keys of different component libraries
Brief description of the concept:
Type safe translations are mandatory not just optional (for TS)
Translations are categorized, means EACH translation will belong to a dedicated category (call it "namespace" if you like).
To achieve a better DX regarding code completion etc., category and term key will not be combined to a string (as in
"someCategory:someKey"
) but passed separately to functions (as in'someCategory', 'someKey'
)Each component will have its own term category/namespace
Categories will be of type
'${string}.${string}'
, for example"shoelace.colorPicker"
(this will later turn out to be very useful)An additional mandatory argument
category
will be added to functionsterm
andLocalizeController.prototype.term
(don't worry, you will not use these functions very often)The constructor of
LocalizeController
will get a second mandatory argumentcategory
Class
LocalizeController
will be enhanced with a new translator methodt(key, ...args)
, similar toterm
but without the need of passing the category (as the category has already been passed to the constructor). Methodthis.localize.term(...)
is still there to have access to all translations (for example cross-cutting translations)It will turn out to make life much easier for the component developers if each component is always bundled with the
en
translations of its own terms (Shoelace is doing this already). This is not necessary, but very handy regarding DX.Localizable components will be implemented as follows:
Translation file
de.ts
(btw: aen.ts
file will not be needed):You may ask "But what about those terms that will be used in multiple components?"
Either use a shared category, e.g. "shoelace.shared" (which I personally would normally not do, in most cases) or provide those terms independently for all involved components (this is what I would do).
For example
clearEntry
is a term that is used for both SL componentsSlInput
andSlSelect
. The other day I've provided a PR for Shoelace with the German translation forclearEntry
which is "Eingabe löschen". While "Eingabe löschen" is a good translation for theSlInput
case, I would have preferred "Auswahl aufheben" (= "Clear selection") for theSlSelect
case. So always using independent terms for different components may not be such a bad thing ("close" is another example: Why not allow to translate contextual to "Close dialog" and "Close tab"?).Beta Was this translation helpful? Give feedback.
All reactions