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

[BUGFIX] Corriger le problème des locales disponibles non-identiques entre pix-site à pix-pro (PIX-14143) #718

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion pix-pro/i18n.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { generateConfig } from '../shared/i18n.config';

const reachableLocales = [
{
// The "code" property should be renamed into "name": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/Locale
code: 'en',
iso: 'en',
file: 'en.js',
// The "name" property should be renamed into "displayName": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/DisplayNames
name: 'English',
icon: 'globe-europe.svg',
domain: process.env.DOMAIN_ORG,
Expand All @@ -27,6 +29,8 @@ const reachableLocales = [
},
];

const reachableLocaleNames = reachableLocales.map(reachableLocale => reachableLocale.code);

const config = generateConfig(reachableLocales);
export default { ...config };
export { reachableLocales };
export { reachableLocales, reachableLocaleNames };
3 changes: 2 additions & 1 deletion pix-pro/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getRoutesToGenerate } from './services/get-routes-to-generate';
import i18nConfig, { reachableLocales } from './i18n.config';
import i18nConfig, { reachableLocales, reachableLocaleNames } from './i18n.config';

export default async () => {
return defineNuxtConfig({
Expand Down Expand Up @@ -28,6 +28,7 @@ export default async () => {
public: {
site: 'https://pro.pix.',
availableLocales: reachableLocales,
availableLocaleNames: reachableLocaleNames,
},
},
nitro: {
Expand Down
6 changes: 5 additions & 1 deletion pix-site/i18n.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { generateConfig } from '../shared/i18n.config';

const reachableLocales = [
{
// The "code" property should be renamed into "name": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/Locale
code: 'en',
iso: 'en',
file: 'en.js',
// The "name" property should be renamed into "displayName": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/DisplayNames
name: 'English',
icon: 'globe-europe.svg',
domain: process.env.DOMAIN_ORG,
Expand Down Expand Up @@ -43,6 +45,8 @@ const reachableLocales = [
},
];

const reachableLocaleNames = reachableLocales.map(reachableLocale => reachableLocale.code);

const config = generateConfig(reachableLocales);
export default { ...config };
export { reachableLocales };
export { reachableLocales, reachableLocaleNames };
3 changes: 2 additions & 1 deletion pix-site/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getRoutesToGenerate } from './services/get-routes-to-generate';
import i18nConfig, { reachableLocales } from './i18n.config';
import i18nConfig, { reachableLocales, reachableLocaleNames } from './i18n.config';

export default async () => {
const routes = process.env.NODE_ENV !== 'test' ? await getRoutesToGenerate({ locales: i18nConfig.locales }) : [];
Expand All @@ -24,6 +24,7 @@ export default async () => {
siteDomain: process.env.SITE_DOMAIN,
formKeysToMap: process.env.FORM_KEYS_TO_MAP || null,
availableLocales: reachableLocales,
availableLocaleNames: reachableLocaleNames,
},
},
nitro: {
Expand Down
33 changes: 27 additions & 6 deletions shared/composables/useLocaleCookie.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
const LOCALE_COOKIE_NAME = 'locale';

export default function useLocaleCookie() {
const appConfig = useAppConfig();
const runtimeConfig = useRuntimeConfig();

const domainFrUrl = new URL(appConfig.domainFr);
const domainOrgUrl = new URL(appConfig.domainOrg);

const previousLocaleCookie = useCookie('locale', {
maxAge: 31536000,
const availableLocaleNames = runtimeConfig.public.availableLocaleNames as Array<string>;

const previousLocaleCookieToDelete = useCookie(LOCALE_COOKIE_NAME, {
maxAge: 31536000, // 1 year
sameSite: 'strict',
});

const localeCookie = useCookie('locale', {
const localeCookie = useCookie(LOCALE_COOKIE_NAME, {
domain: runtimeConfig.public.siteDomain === 'ORG' ? domainOrgUrl.hostname : domainFrUrl.hostname,
maxAge: 31536000,
maxAge: 31536000, // 1 year
sameSite: 'strict',
});

// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
function setLocaleCookie(locale: string, callback?: Function): void {
const localeCanonicalName = Intl.getCanonicalLocales(locale)?.[0];
if (previousLocaleCookie.value) {
previousLocaleCookie.value = null;

if (previousLocaleCookieToDelete.value) {
previousLocaleCookieToDelete.value = null;
}

localeCookie.value = localeCanonicalName;
if (callback) callback();
}

function getBestMatchingLocaleName(localeName: string) {
if (availableLocaleNames.includes(localeName)) {
return localeName;
}

const languageLocaleName = new Intl.Locale(localeName).language;
if (availableLocaleNames.includes(languageLocaleName)) {
return languageLocaleName;
}

return availableLocaleNames[0];
}

return {
localeCookie,
setLocaleCookie,
getBestMatchingLocaleName,
};
}
6 changes: 4 additions & 2 deletions shared/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ definePageMeta({
layout: 'empty',
});

const { localeCookie } = useLocaleCookie();
const { localeCookie, getBestMatchingLocaleName } = useLocaleCookie();
const locale = localeCookie.value;

onBeforeMount(() => {
const router = useRouter();

if (locale) {
return router.replace(`/${locale}/`);
return router.replace(`/${getBestMatchingLocaleName(locale)}/`);
}
});
</script>
44 changes: 44 additions & 0 deletions shared/tests/composables/useLocaleCookie.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { mockNuxtImport } from '@nuxt/test-utils/runtime';

import useLocaleCookie from '../../composables/useLocaleCookie';

const availableLocaleNames = ['en', 'fr', 'fr-fr'];

mockNuxtImport('useCookie', () => {
return () => ({
value: '',
Expand All @@ -18,6 +20,7 @@ mockNuxtImport('useRuntimeConfig', () => {
return () => ({
public: {
siteDomain: 'ORG',
availableLocaleNames,
},
});
});
Expand Down Expand Up @@ -74,4 +77,45 @@ describe('#useLocaleCookie', () => {
});
});
});

describe('getBestMatchingLocaleName', () => {
describe('when wanted locale is available', () => {
test('returns the same locale name', () => {
// given
const { getBestMatchingLocaleName } = useLocaleCookie();

// when
const matchingLocaleName = getBestMatchingLocaleName('fr-fr');

// then
expect(matchingLocaleName).toEqual('fr-fr');
});
});

describe('when wanted locale is unavailable but an available locale with same language is', () => {
test('returns the same locale name', () => {
// given
const { getBestMatchingLocaleName } = useLocaleCookie();

// when
const matchingLocaleName = getBestMatchingLocaleName('fr-be');

// then
expect(matchingLocaleName).toEqual('fr');
});
});

describe('when wanted locale is unavailable and no available locale with same language is', () => {
test('returns the first available locale name', () => {
// given
const { getBestMatchingLocaleName } = useLocaleCookie();

// when
const matchingLocaleName = getBestMatchingLocaleName('nl-be');

// then
expect(matchingLocaleName).toEqual('en');
});
});
});
});