Fix special characters in translation strings (#15872)

* Fix special characters in translation strings

* unit test

Co-authored-by: Brainslug <br41nslug@users.noreply.github.com>
This commit is contained in:
Azri Kahar
2022-10-10 17:49:37 +08:00
committed by GitHub
parent 8e128fecc2
commit fd47923706
5 changed files with 55 additions and 28 deletions

View File

@@ -1,5 +1,6 @@
import { ref, Ref } from 'vue';
import api from '@/api';
import { getLiteralInterpolatedTranslation } from '@/utils/get-literal-interpolated-translation';
import { unexpectedError } from '@/utils/unexpected-error';
import { Language, i18n } from '@/lang';
import { useUserStore } from '@/stores/user';
@@ -126,7 +127,7 @@ export function useTranslationStrings(): UsableTranslationStrings {
if (!cur.key || !cur.translations) return acc;
const translationForCurrentLang = cur.translations.find((t) => t.language === lang);
if (!translationForCurrentLang || !translationForCurrentLang.translation) return acc;
return { ...acc, [cur.key]: translationForCurrentLang.translation };
return { ...acc, [cur.key]: getLiteralInterpolatedTranslation(translationForCurrentLang.translation) };
}, {});
i18n.global.mergeLocaleMessage(lang, localeMessages);
}

View File

@@ -4,6 +4,7 @@ import { Collection as CollectionRaw, DeepPartial, Field } from '@directus/share
import { Collection } from '@/types/collections';
import { getCollectionType } from '@directus/shared/utils';
import { notify } from '@/utils/notify';
import { getLiteralInterpolatedTranslation } from '@/utils/get-literal-interpolated-translation';
import { unexpectedError } from '@/utils/unexpected-error';
import formatTitle from '@directus/format-title';
import { defineStore } from 'pinia';
@@ -56,24 +57,28 @@ export const useCollectionsStore = defineStore({
for (let i = 0; i < collection.meta.translations.length; i++) {
const { language, translation, singular, plural } = collection.meta.translations[i];
const literalInterpolatedTranslation = translation ? translation.replace(/([{}@$|])/g, "{'$1'}") : null;
i18n.global.mergeLocaleMessage(language, {
...(literalInterpolatedTranslation && {
collection_names: {
[collection.collection]: literalInterpolatedTranslation,
},
}),
...(singular && {
collection_names_singular: {
[collection.collection]: singular,
},
}),
...(plural && {
collection_names_plural: {
[collection.collection]: plural,
},
}),
...(translation
? {
collection_names: {
[collection.collection]: getLiteralInterpolatedTranslation(translation),
},
}
: {}),
...(singular
? {
collection_names_singular: {
[collection.collection]: getLiteralInterpolatedTranslation(singular),
},
}
: {}),
...(plural
? {
collection_names_plural: {
[collection.collection]: getLiteralInterpolatedTranslation(plural),
},
}
: {}),
});
}
}

View File

@@ -2,6 +2,7 @@ import api from '@/api';
import { i18n } from '@/lang';
import { useCollectionsStore } from '@/stores/collections';
import { useRelationsStore } from '@/stores/relations';
import { getLiteralInterpolatedTranslation } from '@/utils/get-literal-interpolated-translation';
import { unexpectedError } from '@/utils/unexpected-error';
import formatTitle from '@directus/format-title';
import { DeepPartial, Field, FieldRaw, Relation } from '@directus/shared/types';
@@ -75,17 +76,16 @@ export const useFieldsStore = defineStore({
for (let i = 0; i < field.meta.translations.length; i++) {
const { language, translation } = field.meta.translations[i];
// Interpolate special characters in vue-i18n to prevent parsing error. Ref #11287
const literalInterpolatedTranslation = translation ? translation.replace(/([{}@$|])/g, "{'$1'}") : null;
i18n.global.mergeLocaleMessage(language, {
...(literalInterpolatedTranslation && {
fields: {
[field.collection]: {
[field.field]: literalInterpolatedTranslation,
},
},
}),
...(translation
? {
fields: {
[field.collection]: {
[field.field]: getLiteralInterpolatedTranslation(translation),
},
},
}
: {}),
});
}
}

View File

@@ -0,0 +1,10 @@
import { test, expect } from 'vitest';
import { getLiteralInterpolatedTranslation } from '@/utils/get-literal-interpolated-translation';
test('No special characters', () => {
expect(getLiteralInterpolatedTranslation('folding at home')).toBe('folding at home');
});
test('With special characters', () => {
expect(getLiteralInterpolatedTranslation('folding@home')).toBe(`folding{'@'}home`);
});

View File

@@ -0,0 +1,11 @@
/**
* Literal interpolation to use special characters such as "{", "}", "@", "$", and "|" in app translations
*
* @param translation - vue i18n translation string
* @returns - literal interpolated translation string
*
* @see {@link https://github.com/directus/directus/pull/11287}
*/
export function getLiteralInterpolatedTranslation(translation: string) {
return translation.replace(/([{}@$|])/g, "{'$1'}");
}