slang icon indicating copy to clipboard operation
slang copied to clipboard

What about l10n?

Open lucavenir opened this issue 2 years ago • 8 comments

Hi there, thank you for this awesome lib.

I realize that slang is about i18n, but are there any plans to move this library towards a l10n approach? It might sound like this is an "out-of-scope" proposal, but hear me out for a bit.

Motivation, Use cases

Most of the motivation arises from the necessity to properly format numbers, and maybe add some global or per-string configuration.

Take this example from the docs

# File: strings.i18n.yaml
someKey:
  apple:
    one: "I have $n apple.",
    other: "I have $n apples."

Now, say that such quantitative number that needs a proper formatting; there's a good chance that this most likely depends on where you're translating that sentence, even in the same language.

Say we have a thousands apples. Here's how you would count them in London: 1.000,00 apples. Here's how you could count them in Dublin: 1,000.00 apples.

And that's weird enough, thinking it's the same lang and the two cities are 450km apart (: Well, to be fair this also depends on personal preference, culture and context usage; thus the distinction line in this use case is thin.

Nonetheless, when you have a currency instead of simple apples; things get interesting.

# File: strings.i18n.yaml
someCurrencyKey:
  amount: "I feel rich, since I have $n $currency." # warn: pseudocode that doesn't make much sense, but bear with me

I'd expect amount to be properly formatted, or at least I'd expect our tool to give me some degree of freedom when formatting such number (different contexts may or may not follow their locale conventions).

Say we are rich and we want to show it off with an explicit format. Here's how you would do that in London: £ 1,000,000.00 GBP. Here's how you would do that in Dublin: 1.000.000,00 € EUR.

Current state

Can we achieve this at this point in time?

Here's my guess (and I'm not sure, so let me know if there're better alternatives):

  1. Rely on intl
  2. Carefully write reusable boilerplate code for your use cases
  3. Inject it into slang strings

The proposal

Shortly, this proposal is about easening our developer experience when creating translatable sentences that involve numbers and their formatting. The default should be the following: current locale settings should apply first, then global settings kick in (build.yaml config file) and finally per-string settings apply.

Here's a heavily personalized string example:

# File: strings.i18n.yaml
someKey:
  # warn: pseudocode
  sentence: "Where lambo? I have $n!"
    - type: number
    - format: currency
    - decimalDigits: 2
    - name: GBP
    - symbol: £
    - customPattern: "¤ #,##0.00"

Usage:

final lambo = t.someKey.sentence(0xFFFFFF);
print(lambo); // "Where lambo? I have £ 16,777,215.00!"

Note how this example relies onto dart APIs from the intl package, which (if I'm not mistaken) are ISO-like conventions. Obviously the previous example would be tedious to repeat for each string. That's were global configs and current locale would kick in as default fall-offs.

Beyond simple numbers

Another l10n topic is date formatting. Even here, we could rely on intl and give a similar configuration API and usage:

# File: strings.i18n.yaml
someKey:
  # warn: pseudocode
  sentence1: "Morning! Oh, today it's $date!"
    - type: datetime
    - format: MMMMEEEEd # MONTH_WEEKDAY_DAY from intl package
  sentence2: "Good Heavens, just look at the time! It's $time!"
    - type: datetime
    - format: Hm # HOUR24_MINUTE from intl package

Usage:

const myValue = const DateTime.utc(2022, 10, 29, 03, 30, 00);

// The following is a mock of running this code in a GMT-5 time zone
final dateAlabama = t.someKey.sentence1(myValue);
print(morningAlabama); // "Morning! Oh, today it's Friday, October 28"
final timeAlabama = t.someKey.sentence2(myValue);
print(timeAlabama); // "Good Heavens, just look at the time! It's 22:30!"


// The following is a mock of running this code in a GMT+1 time zone
final dateEurope = t.someKey.sentence1(myValue);
print(morningAlabama); // "Morning! Oh, today it's Saturday, October 29"
final timeEurope = t.someKey.sentence2(myValue);
print(timeAlabama); // "Good Heavens, just look at the time! It's 04:30!"

Let me know what you think about this.

lucavenir avatar Oct 29 '22 08:10 lucavenir