Skip to main content

Functional Specification: Multi-language Entity Binding & Mobile Deep-link Translation Routing

Last Updated: 16/07/2026
Type: Functional Specification — Localization (i18n) & Routing
Scope: CMS Admin Panel (Translation Bindings) & Mobile App Navigation (Language Switcher)
Severity: šŸ”“ High — Essential for international users; prevents navigation breakage when changing language in-app

Feedback Reference:


1. Overview & Business Requirements​

The Golden Membership system serves multi-lingual customers (Vietnamese, English, Chinese, Korean, Japanese).

To ensure a seamless user experience:

  1. CMS Admin (Inline Translations): Admin should edit different language versions of the same banner, article, or event within the same form context. These translations must be bound together under a single group identifier.
  2. Mobile App (State Persistence on Translation): If a user is viewing a detail screen (e.g., an Article detail screen) and decides to switch the app language, the app must reload the current screen using the linked translation ID/slug. It must NOT crash, throw a 404, or force-exit the user back to the Home screen.

2. CMS Backend & Database Translation Architecture​

To link translations together, we use a Translation Group Model. Each article, event, or banner does not float independently; it is bound to a translation group:

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ Translation Group Card │
│ (translationGroupId: 999) │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
│
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
ā–¼ ā–¼ ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ Locale: "vi" │ │ Locale: "en" │ │ Locale: "ko" │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤ ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤ ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ ID: 123 │ │ ID: 124 │ │ ID: 125 │
│ Slug: uu-dai-he │ │ Slug: summer-pkg│ │ Slug: summer-ko │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

2.1 Database Schema (Example)​

interface TranslationGroup {
id: string;
type: 'article' | 'event' | 'banner';
createdAt: Date;
}

interface Article {
id: string;
translationGroupId: string; // āœ… Links all translations together
locale: 'vi' | 'en' | 'zh' | 'ko' | 'ja';
title: string;
slug: string;
body: string;
// ...other fields
}

2.2 CMS Interface Requirements​

  • When editing a banner/article, changing the language dropdown (VI, EN, etc.) in the sidebar must save the current locale's fields and fetch the inputs for the selected locale within the same editing session (inline).
  • If a translation does not exist yet for the selected language, show an empty form with an "Add Translation" button.

3. Mobile App Navigation & Translation Reloading​

When the user changes the app language setting, the mobile app triggers a global language update. We must intercept this event to reload the active view parameters:

3.2 Dynamic Route Parameter Mapping​

Current Screen Stack: ArticleDetailScreen (params: { id: 123, slug: 'uu-dai-he' })
↓
User opens settings → Change language to English ("en")
↓
App calls API: GET /api/translations/resolve?fromId=123&targetLocale=en
↓
API returns linked ID: { targetId: 124, targetSlug: 'summer-pkg' }
↓
App updates route params: navigate('ArticleDetail', { id: 124, slug: 'summer-pkg' })
↓
Current screen stays active and re-fetches the English content.
(User is NOT redirected to Home)

3.3 React Native Navigation Handler Example​

import React, { useEffect } from 'react';
import { useNavigation, useRoute } from '@react-navigation/native';
import { useLanguage } from '../context/LanguageContext';

export const ArticleDetailScreen = () => {
const route = useRoute();
const navigation = useNavigation();
const { currentLanguage } = useLanguage();
const { id } = route.params;

useEffect(() => {
const resolveAndSwitchTranslation = async () => {
try {
// Query the API to find the translation ID for the new language
const response = await api.resolveTranslationId({
currentId: id,
targetLocale: currentLanguage
});

if (response.targetId && response.targetId !== id) {
// Update the screen navigation stack in place with the correct translation ID
navigation.setParams({ id: response.targetId });
}
} catch (error) {
console.warn("Could not resolve translated entity ID", error);
// Fallback: stay on current id or handle gracefully. Do NOT force goBack() to Home.
}
};

resolveAndSwitchTranslation();
}, [currentLanguage]); // Triggers automatically when app language changes

// Fetch and render content normally based on route.params.id...
};

Technical Checklist​

CMS Backend & Database:

  • Implement translationGroupId binding on Article, Event, and Banner schemas.
  • Create a translation resolver endpoint: GET /api/translations/resolve?fromId=<id>&targetLocale=<locale>.
  • Update the CMS save controller: ensure translating an entity updates/saves under the same translationGroupId rather than spawning unrelated items.

CMS Admin UI:

  • Build the inline language selector panel. Tapping a new language must save current drafts and toggle local input fields inline.

Mobile App:

  • Intercept language switch actions on detail screens (Articles, Events).
  • Implement navigation.setParams() or route updates to reload content with the matched translated ID instead of pushing to root/home.
  • Handle error states: if no translation exists for the target language, display the original version but wrap it in a notification banner (e.g. "This article is only available in Vietnamese").
  • Validate on iOS and Android: open an article detail, change app language from settings, and confirm the details reload correct language content in place.