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

Datetime and number format incorrectly falls back when not defined #2039

Closed
4 tasks done
pcdevil opened this issue Nov 30, 2024 · 2 comments
Closed
4 tasks done

Datetime and number format incorrectly falls back when not defined #2039

pcdevil opened this issue Nov 30, 2024 · 2 comments

Comments

@pcdevil
Copy link

pcdevil commented Nov 30, 2024

Reporting a bug?

When there is no dateTimeFormats or numberFormats for a given language, the translate methodss use the fallback locale to format the given input.

Expected behavior

The d(new Date(), 'formatName') and n(1234567.89, 'formatName') calls should respect the current locale value and only use of the dateTimeFormat / numberFormat option from the fallback.

Reproduction

StackBlitz playground: vue-i18n-dn-test

  1. Initialise Vue I18n with two languages but define a date time and number format only for the fallback:
    const i18n = createI18n({
      locale: 'hu-HU',
      fallbackLocale: 'en-GB',
      messages: {
        'en-GB': { /* ... */ },
        'hu-HU': { /* ... */ },
      },
    
      datetimeFormats: {
        'en-GB': {
          shortDate: { dateStyle: 'short' },
        },
        'hu-HU': {
          // empty
        },
      },
    
      numberFormats: {
        'en-GB': {
          forintCurrency: {
            currency: 'HUF',
            currencyDisplay: 'narrowSymbol',
            style: 'currency',
          },
        },
        'hu-HU': {
          // empty
        },
      },
    });
    full source: main.ts
  2. Set the locale to the one without the defined formats
  3. Use d() or n() with the format defined in the fallback locale:
    <script setup>
    const { d, n } = useI18n();
    
    const dateTest = computed(() => d(new Date(), 'shortDate'));
    const numberTest = computed(() => n(1234567.89, 'forintCurrency'));
    </script>
    
    <template>
      <p>dateTest: {{ dateTest }}</p>
      <p>numberTest: {{ numberTest }}</p>
    </template>
    full source: App.vue
    • Alternatively, use <i18n-d> and <i18n-n> and do the same:
      <template>
        <i18n-d format="shortDate" :value="new Date()" />
        <i18n-n format="forintCurrency" :value="1234567.89" />
      </template>

Actual behaviour

  • The date is displayed as 30/11/2024 instead of 2024. 11. 30.
  • The number is displayed as Ft 1,234,567.89 instead of 1 234 567,89 Ft

System Info

System:
  OS: Linux 5.15 Ubuntu 22.04.5 LTS 22.04.5 LTS (Jammy Jellyfish)
  CPU: (12) x64 Intel(R) Core(TM) i5-10600 CPU @ 3.30GHz
  Memory: 56.79 GB / 62.62 GB
  Container: Yes
  Shell: 5.8.1 - /usr/bin/zsh
Binaries:
  Node: 20.15.1 - /run/user/1000/fnm_multishells/2890037_1732975662492/bin/node
  pnpm: 9.5.0 - /run/user/1000/fnm_multishells/2890037_1732975662492/bin/pnpm
npmPackages:
  @intlify/core-base: ^10.0.4 => 10.0.4 
  @vitejs/plugin-vue: ^5.1.3 => 5.1.3 
  @vue/eslint-config-typescript: ^13.0.0 => 13.0.0 
  @vue/test-utils: ^2.4.6 => 2.4.6 
  @vue/tsconfig: ~0.5.1 => 0.5.1 
  vite: ^5.4.6 => 5.4.6 
  vite-tsconfig-paths: ^4.3.2 => 4.3.2 
  vitest: ^2.1.1 => 2.1.1 
  vue: ^3.5.6 => 3.5.6 
  vue-i18n: ^10.0.4 => 10.0.4 
  vue-tsc: ^2.1.6 => 2.1.6

Screenshot

image

Additional context

  • I opted to declare en-GB instead of en to avoid ambiguity around the date part order.
  • Added "Intl test" lines for the playground to show how the date and number are properly formatted with hu-HU locale. These tests use the locale set in vue-i18n but call the Intl methods directly.

Validations

@pcdevil pcdevil added the Status: Review Needed Request for review comments label Nov 30, 2024
@kazupon
Copy link
Member

kazupon commented Dec 3, 2024

Thank you for your feedback!
I've just see the your reproduction.

I have checked at your App.vue, but there are no options specified for useI18n. Therefore, on App.vue, the locale operates in the global scope. In other words, it is hu-HU.
(about locale scope, you can see in there: https://vue-i18n.intlify.dev/guide/essentials/scope.html )

Since hu-HU is empty, en-GB is used for dateTimeFormats and numberFormats.

So , This report behaves as expected for vue-i18n

Thank you!

@kazupon kazupon closed this as completed Dec 3, 2024
@kazupon kazupon removed the Status: Review Needed Request for review comments label Dec 3, 2024
@pcdevil
Copy link
Author

pcdevil commented Dec 3, 2024

I have checked at your App.vue, but there are no options specified for useI18n. Therefore, on App.vue, the locale operates in the global scope. In other words, it is hu-HU.

that's exactly what I'd expect: the locale is set to Hungarian and therefore the labels are shown in that language too!

I see now where my expectation and Vue I18n's behaviour differs: while the package handles the situation by using the fallback locale's definition and the locale itself, I expected to only use the format option but keep the current locale 🤔
I could reason why my thinking makes sense, but I also see the implemented approach has benefits, just wasn't necessary obvious when I was reading the documentation!

If I'm mistaken the this forces me to define all datetime and number formats for every language, or to create a mechanism that assigns the missing definitions to every locale when assigning the i18nOptions. I don't think it's a big deal, but certainly creates friction when the format options don't deviate too much.

In any case, it's good to know the behaviour is intended and no further action is needed, thank you for the explanation Kazuya!

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

2 participants