feat(i18n): display only active language in translation fields
Update TranslationFields to render a single input for the current locale Ensure entity base names fallback to the active locale translation on save
This commit is contained in:
@@ -18,9 +18,21 @@ const emit = defineEmits<{
|
|||||||
'update:translations': [value: TranslationMap];
|
'update:translations': [value: TranslationMap];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { locale, t } = useI18n();
|
||||||
|
const fallbackLanguage: Language = { code: 'en', name: 'English', enabled: true, isDefault: true, sortOrder: 0 };
|
||||||
const visibleLanguages = computed(() => props.languages.filter((language) => language.enabled));
|
const visibleLanguages = computed(() => props.languages.filter((language) => language.enabled));
|
||||||
const defaultLanguage = computed(() => visibleLanguages.value.find((language) => language.isDefault) ?? visibleLanguages.value[0]);
|
const defaultLanguage = computed(() => visibleLanguages.value.find((language) => language.isDefault) ?? visibleLanguages.value[0] ?? fallbackLanguage);
|
||||||
|
const currentLanguage = computed(() => {
|
||||||
|
const currentLocale = String(locale.value || defaultLanguage.value.code);
|
||||||
|
return visibleLanguages.value.find((language) => language.code === currentLocale) ?? defaultLanguage.value;
|
||||||
|
});
|
||||||
|
const isDefaultLanguage = computed(() => currentLanguage.value.code === defaultLanguage.value.code);
|
||||||
|
const currentValue = computed({
|
||||||
|
get: () => fieldValue(currentLanguage.value),
|
||||||
|
set: (value: string) => updateField(currentLanguage.value, value)
|
||||||
|
});
|
||||||
|
const currentPlaceholder = computed(() => fieldPlaceholder(currentLanguage.value));
|
||||||
|
const currentRequired = computed(() => Boolean(props.required && (isDefaultLanguage.value || props.baseValue.trim() === '')));
|
||||||
|
|
||||||
function fieldValue(language: Language): string {
|
function fieldValue(language: Language): string {
|
||||||
if (language.code === defaultLanguage.value?.code) {
|
if (language.code === defaultLanguage.value?.code) {
|
||||||
@@ -58,23 +70,19 @@ function updateField(language: Language, value: string) {
|
|||||||
emit('update:translations', nextTranslations);
|
emit('update:translations', nextTranslations);
|
||||||
}
|
}
|
||||||
|
|
||||||
function inputValue(event: Event): string {
|
|
||||||
return event.target instanceof HTMLInputElement ? event.target.value : '';
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="translation-fields">
|
<div class="translation-fields">
|
||||||
<div v-for="language in visibleLanguages" :key="language.code" class="field">
|
<div class="field">
|
||||||
<label :for="`${idPrefix}-${language.code}`">
|
<label :for="`${idPrefix}-${currentLanguage.code}`">
|
||||||
{{ t('common.fieldForLanguage', { field: label, language: language.name }) }}
|
{{ t('common.fieldForLanguage', { field: label, language: currentLanguage.name }) }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
:id="`${idPrefix}-${language.code}`"
|
:id="`${idPrefix}-${currentLanguage.code}`"
|
||||||
:value="fieldValue(language)"
|
v-model="currentValue"
|
||||||
:placeholder="fieldPlaceholder(language)"
|
:placeholder="currentPlaceholder"
|
||||||
:required="required && language.code === defaultLanguage?.code"
|
:required="currentRequired"
|
||||||
@input="updateField(language, inputValue($event))"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -248,6 +248,14 @@ function configBaseNameForSave() {
|
|||||||
return configForm.value.translations[currentConfigLocale.value]?.name ?? '';
|
return configForm.value.translations[currentConfigLocale.value]?.name ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checklistTitleForSave() {
|
||||||
|
if (checklistForm.value.title.trim() !== '') {
|
||||||
|
return checklistForm.value.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return checklistForm.value.translations[currentConfigLocale.value]?.title ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
function previewChecklistOrder(rows: DailyChecklistItem[]) {
|
function previewChecklistOrder(rows: DailyChecklistItem[]) {
|
||||||
checklistRows.value = rows;
|
checklistRows.value = rows;
|
||||||
}
|
}
|
||||||
@@ -391,7 +399,7 @@ async function loadChecklist() {
|
|||||||
async function saveChecklistItem() {
|
async function saveChecklistItem() {
|
||||||
await run(async () => {
|
await run(async () => {
|
||||||
const payload = {
|
const payload = {
|
||||||
title: checklistForm.value.title,
|
title: checklistTitleForSave(),
|
||||||
translations: checklistForm.value.translations
|
translations: checklistForm.value.translations
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type HabitatAppearanceForm = {
|
|||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { locale, t } = useI18n();
|
||||||
const options = ref<Options | null>(null);
|
const options = ref<Options | null>(null);
|
||||||
const itemRows = ref<Item[]>([]);
|
const itemRows = ref<Item[]>([]);
|
||||||
const pokemonRows = ref<Pokemon[]>([]);
|
const pokemonRows = ref<Pokemon[]>([]);
|
||||||
@@ -127,6 +127,15 @@ function closeEditor() {
|
|||||||
void router.push(cancelTo.value);
|
void router.push(cancelTo.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function habitatNameForSave() {
|
||||||
|
const baseName = habitatForm.value.name.trim();
|
||||||
|
if (baseName !== '') {
|
||||||
|
return habitatForm.value.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return habitatForm.value.translations[String(locale.value || '')]?.name ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
async function loadEditor() {
|
async function loadEditor() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
message.value = '';
|
message.value = '';
|
||||||
@@ -189,7 +198,7 @@ async function saveHabitat() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const payload: HabitatPayload = {
|
const payload: HabitatPayload = {
|
||||||
name: habitatForm.value.name,
|
name: habitatNameForSave(),
|
||||||
translations: habitatForm.value.translations,
|
translations: habitatForm.value.translations,
|
||||||
recipeItems: toQuantityRows(habitatForm.value.recipeItems),
|
recipeItems: toQuantityRows(habitatForm.value.recipeItems),
|
||||||
pokemonAppearances: habitatForm.value.pokemonAppearances
|
pokemonAppearances: habitatForm.value.pokemonAppearances
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { api, type ConfigType, type ItemPayload, type Language, type Options, ty
|
|||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { locale, t } = useI18n();
|
||||||
const options = ref<Options | null>(null);
|
const options = ref<Options | null>(null);
|
||||||
const languages = ref<Language[]>([]);
|
const languages = ref<Language[]>([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@@ -53,6 +53,15 @@ function closeEditor() {
|
|||||||
void router.push(cancelTo.value);
|
void router.push(cancelTo.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function itemNameForSave() {
|
||||||
|
const baseName = itemForm.value.name.trim();
|
||||||
|
if (baseName !== '') {
|
||||||
|
return itemForm.value.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemForm.value.translations[String(locale.value || '')]?.name ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
async function loadOptions() {
|
async function loadOptions() {
|
||||||
const [loadedOptions, loadedLanguages] = await Promise.all([api.options(), api.languages()]);
|
const [loadedOptions, loadedLanguages] = await Promise.all([api.options(), api.languages()]);
|
||||||
options.value = loadedOptions;
|
options.value = loadedOptions;
|
||||||
@@ -131,7 +140,7 @@ async function saveItem() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const payload: ItemPayload = {
|
const payload: ItemPayload = {
|
||||||
name: itemForm.value.name,
|
name: itemNameForSave(),
|
||||||
translations: itemForm.value.translations,
|
translations: itemForm.value.translations,
|
||||||
categoryId: Number(itemForm.value.categoryId),
|
categoryId: Number(itemForm.value.categoryId),
|
||||||
usageId: itemForm.value.usageId ? Number(itemForm.value.usageId) : null,
|
usageId: itemForm.value.usageId ? Number(itemForm.value.usageId) : null,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type SkillItemDropForm = {
|
|||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { locale, t } = useI18n();
|
||||||
const options = ref<Options | null>(null);
|
const options = ref<Options | null>(null);
|
||||||
const itemOptions = ref<NamedEntity[]>([]);
|
const itemOptions = ref<NamedEntity[]>([]);
|
||||||
const languages = ref<Language[]>([]);
|
const languages = ref<Language[]>([]);
|
||||||
@@ -87,6 +87,15 @@ function skillDropLabel(skillId: string) {
|
|||||||
return name ? t('pages.pokemon.skillDrop', { name }) : t('pages.pokemon.dropItem');
|
return name ? t('pages.pokemon.skillDrop', { name }) : t('pages.pokemon.dropItem');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pokemonNameForSave() {
|
||||||
|
const baseName = pokemonForm.value.name.trim();
|
||||||
|
if (baseName !== '') {
|
||||||
|
return pokemonForm.value.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pokemonForm.value.translations[String(locale.value || '')]?.name ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
function closeEditor() {
|
function closeEditor() {
|
||||||
void router.push(cancelTo.value);
|
void router.push(cancelTo.value);
|
||||||
}
|
}
|
||||||
@@ -164,7 +173,7 @@ async function savePokemon() {
|
|||||||
try {
|
try {
|
||||||
const payload: PokemonPayload = {
|
const payload: PokemonPayload = {
|
||||||
id: Number(isEditing.value ? routeId.value : pokemonForm.value.id),
|
id: Number(isEditing.value ? routeId.value : pokemonForm.value.id),
|
||||||
name: pokemonForm.value.name,
|
name: pokemonNameForSave(),
|
||||||
translations: pokemonForm.value.translations,
|
translations: pokemonForm.value.translations,
|
||||||
environmentId: Number(pokemonForm.value.environmentId),
|
environmentId: Number(pokemonForm.value.environmentId),
|
||||||
skillIds: toIds(pokemonForm.value.skillIds.slice(0, 2)),
|
skillIds: toIds(pokemonForm.value.skillIds.slice(0, 2)),
|
||||||
|
|||||||
Reference in New Issue
Block a user