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

formatMessage with ICU behave different then formatNumber #4350

Closed
idoodler opened this issue Feb 5, 2024 · 2 comments
Closed

formatMessage with ICU behave different then formatNumber #4350

idoodler opened this issue Feb 5, 2024 · 2 comments

Comments

@idoodler
Copy link

idoodler commented Feb 5, 2024

Which package?

react-intl

Describe the bug

When formatting a string that contains a number using formatMessage I get the US style number format, but If I format the same number using formatNumber its correctly formated using the German format.

I see this behaviour on my iPhone which is in the Region "Germany" with Language "Germany". The Locale is correctly set and returns de.

To Reproduce

Codesandbox URL

Not aplicable

Reproducible Steps/Repo

Steps to reproduce the behavior:

import './polyfills'; // Here we do import all the react-intl polyfils for native platforms, including all the locale-data files we need
import {
	findBestLanguageTag,
	getLocales,
	getTimeZone,
} from 'react-native-localize';
import { locales } from '../locales';
import { createIntl, createIntlCache } from 'react-intl';

if ('__setDefaultTimeZone' in Intl.DateTimeFormat) {
	// @ts-expect-error __setDefaultTimeZone is not in the type definition
	Intl.DateTimeFormat.__setDefaultTimeZone(getTimeZone());
}

const defaultLocale = 'en-US';
const cache = createIntlCache();

const getBestLanguageTag = () => {
	const deviceLocales = getLocales();
	return (
		findBestLanguageTag(
			[
				...Object.values(deviceLocales).map(
					({ languageCode }) => languageCode,
				),
				...Object.values(deviceLocales).map(
					({ languageTag }) => languageTag,
				),
			].filter(langTag => Object.keys(locales).includes(langTag)),
		) ?? {
			languageTag: defaultLocale,
		}
	);
};

const { languageTag: locale } = getBestLanguageTag();

const getIntl = () =>
	createIntl(
		{
			locale,
			messages: locales[locale],
			defaultLocale,
			onError: error => {
				if (error.code === 'MISSING_TRANSLATION') {
					return;
				}
				throw error;
			},
		},
		cache,
	);

export const intl = getIntl();
export { locale };
import {intl, locale} from `./translationProvider` // Same file as above
appLogger.debug('Internationalization', {
	locale,
	symbols:
		Intl.NumberFormat.localeData?.[locale]?.numbers.symbols.latn,
});
const formatTest = 100000.1234;
appLogger.debug('Internationalization', {
	number: `${formatTest.toFixed(4)} = ${intl.formatNumber(formatTest)}`,
	message: `${formatTest.toFixed(4)} = ${intl.formatMessage(
		{
			defaultMessage: '{val, number}',
		},
		{
			val: formatTest,
		},
	)}`,
});

Expected behavior

In the locale de both results should be 100.000,123, not 100,000.123

Screenshots

Bildschirmfoto 2024-02-05 um 19 02 45

Desktop (please complete the following information):

  • OS: maCOS
  • Browser: -
  • Version -

Smartphone (please complete the following information):

  • Device: iPhone 15 Pro
  • OS: iOS 17.3
  • Browser: -
  • Version -
@idoodler idoodler added the bug label Feb 5, 2024
@idoodler
Copy link
Author

idoodler commented Feb 6, 2024

I can work around it in the first file

const getIntl = () =>
    createIntl(
        {
            locale,
            messages: locales[locale],
            defaultLocale,
            onError: error => {
                if (error.code === 'MISSING_TRANSLATION') {
                    return;
                }
                throw error;
            },
        },
        cache,
    );

const internalIntl = getIntl();
const formatMessageOverride: typeof internalIntl.formatMessage<string> = (
    ...args: Parameters<typeof internalIntl.formatMessage<string>>
) => {
    const [description, values, opts] = args;
    return internalIntl.formatMessage<string>(description, values, {
        ...(opts ?? {}),
        formatters: {
            // @ts-ignore
            getDateTimeFormat: internalIntl.formatters.getDateTimeFormat,
            getPluralRules: internalIntl.formatters.getPluralRules,
            ...(opts?.formatters ?? {}),
            getNumberFormat: (locals, opts) => {
                return {
                    ...internalIntl.formatters.getNumberFormat(locals, opts),
                    format: internalIntl.formatNumber,
                };
            },
        },
    });
};
export const intl = {
    ...internalIntl,
    formatMessage: formatMessageOverride,
    $t: formatMessageOverride,
};
Bildschirmfoto 2024-02-06 um 06 55 08

Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the Stale label Mar 10, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant