Aller au contenu
14 octobre 20269 min readGuides

Un produit, de nombreux clients : des traductions par client avec les tenants, un exemple pas à pas

Les traductions par client (aussi appelées surcharges de tenant) permettent à un produit de parler la langue de chaque client, au sens propre comme au sens commercial : la même application dit « patient » pour un cabinet et « client » pour un autre, annonce ici une politique d'annulation de 24 heures et là une de 48 heures, et affiche le nom du client au lieu du vôtre, tandis que tout le reste demeure un seul ensemble de traductions partagé. Ce billet compare les façons dont les équipes construisent cela, puis déroule un vrai essai : un projet de base, trois tenants clients, leurs surcharges, ce qui s'est passé quand le texte de base a changé, et comment l'application charge le bon client.

Faits clés
  • Stocker la différence, pas une copie : un tenant hérite de chaque clé et de chaque traduction de la base et ne conserve que ses surcharges. Les nouvelles clés de la base et les changements de la base atteignent chaque tenant qui ne les a pas surchargés.
  • Les surcharges ne suivent pas la base : le texte d'un client reste le sien jusqu'à ce qu'il soit supprimé dans le tenant. Le « check tenants » de l'éditeur montre qui surcharge une clé, avec la valeur.
  • Un ID de projet par client : l'application charge le tenant qu'elle sert ; les fichiers du CDN combinent déjà base et surcharges, et les fichiers d'un tenant sont republiés quand la base change (avec la publication automatique ; sinon quand vous publiez la base).
  • Seules les surcharges coûtent des mots : le texte hérité n'est pas compté deux fois. Les tenants sont disponibles à partir du plan Growth (5 inclus).

Cinq façons de gérer une formulation par client

ApprocheFonctionnementConvient quandSe complique quand
Une copie par clientDupliquer les fichiers de langue ou le projet TMS pour chaque clientun ou deux clients, un produit qui change rarementchaque changement de la base doit être recopié dans chaque copie, et les copies divergent
Codes de langue personnalisésUn code comme de-x-physio ne contient que les clés modifiées ; i18next se replie sur de pour le resteune poignée de clients, les développeurs sont responsables des fichiersle nombre de clients multiplié par celui des langues multiplie les fichiers ; les traducteurs voient des dizaines de pseudo-langues
Un namespace par clientUn namespace physio-north chargé avant le namespace partagépeu de clés diffèrentl'ordre de recherche se trouve dans la configuration i18next de chaque application (fallbackNS), et les namespaces se multiplient par client
Interpolation{{brand}} ou {{hours}} dans les chaînesseules des valeurs diffèrent (un nom de marque, un nombre d'heures)la terminologie ou le ton diffèrent au-delà de quelques variantes que le context d'i18next peut couvrir
Projets tenantsUn projet par client qui hérite d'un projet de base et stocke les surchargesbeaucoup de clients, chacun avec sa propre formulation, ses propres utilisateurs et ses propres accèsles surcharges doivent être vérifiées quand la base change ; il faut le plan Growth ou supérieur, et des packs au-delà des tenants inclus ; et pour des clients dont les produits diffèrent vraiment, des projets séparés sont plus simples

Les quatre premières ne demandent aucun outillage particulier, et la deuxième est une configuration i18next tout à fait valable pour quelques clients. La suite de ce billet porte sur la cinquième, où un client de plus est un tenant de plus, pas une copie de plus.

L'exemple

ClinicDesk est une application de prise de rendez-vous pour cabinets, vendue en marque blanche. Ses trois clients sont inventés pour cet exemple :

ClientCe qu'il veut de différent
Physio North« Client » au lieu de « patient », son propre nom, sa propre phrase de support
Praxis am SeeUn délai d'annulation de 48 heures au lieu de 24 heures, son propre nom, sa propre phrase de support
Smile DentalSeulement son propre nom

Le projet de base compte 15 clés en anglais, en allemand et en français (le français ajoute une forme de pluriel).

Étape 1 : le projet de base

La base contient la formulation propre au produit : navigation, boutons, parcours de réservation, SMS de rappel, politique d'annulation. Nous avons signalé les 15 clés anglaises avec une phrase de contexte chacune, et la traduction automatique a rempli l'allemand et le français. Par exemple, la politique est devenue « Sie können bis zu 24 Stunden vor Ihrem Termin kostenfrei stornieren. » et « Vous pouvez annuler sans frais jusqu'à 24 heures avant votre rendez-vous. »

Étape 2 : un tenant par client

Sur la page multi-tenant du projet, chaque client reçoit un tenant : un projet à part entière, créé à partir de la base. Avec can't deviate from parent activé (le réglage par défaut), un tenant a toujours les langues et les namespaces de la base : une nouvelle langue dans la base apparaît donc dans chaque tenant.

Les tenants du projet de base ClinicDesk dans l'application Locize : Physio North, Praxis am See et Smile Dental, chacun contraint de correspondre au parent (capture faite pendant l'essai du projet)

Chaque tenant a son propre ID de projet, ses propres utilisateurs et ses propres clés API. Les personnes d'un client peuvent être invitées dans leur seul tenant et ne voient pas les autres clients ; votre propre équipe, en tant que membres de votre organisation, a accès à tous.

Étape 3 : la formulation propre à chaque client

Les surcharges sont des modifications ordinaires dans le tenant : dans l'éditeur, via l'API ou, comme ici, via le serveur MCP. Nous avons écrit les surcharges anglaises de chaque client : six pour Physio North, trois pour Praxis am See, une pour Smile Dental :

CléBase (anglais)Physio NorthPraxis am SeeSmile Dental
app.titleClinicDeskPhysio NorthPraxis am SeeSmile Dental
nav.patientsPatientsClients(base)(base)
patients.addAdd patientAdd client(base)(base)
patients.labelPatientClient(base)(base)
patients.searchSearch patientsSearch clients(base)(base)
appointments.cancelPolicy... up to 24 hours before ...(base)... up to 48 hours before ...(base)
footer.supportQuestions? Contact the ClinicDesk support team.Questions? Contact the Physio North front desk.Questions? Call the practice team.(base)

Une chose que nous n'avions pas prévue : dès que les surcharges anglaises de Physio North ont été enregistrées, la traduction automatique du tenant en a tiré des ébauches en allemand et en français, chacune avec un score de confiance et marquée à relire. Nous avons réécrit la phrase de support dans les deux langues et laissé les cinq autres ébauches à la relecture du client. La politique de 48 heures de Praxis am See a été ébauchée de la même façon (« 48 heures » en français) ; nous avons gardé l'ébauche française et remplacé l'allemande. Cela se produit quand la traduction automatique est activée dans le tenant (il reprend le réglage de la base au moment de sa création) et que la surcharge arrive via l'API, la CLI ou MCP sous la forme d'une clé que le tenant n'avait pas encore ; une surcharge saisie dans l'éditeur, ou une deuxième modification d'une surcharge existante, n'est pas ébauchée, sauf si vous demandez une traduction.

Dans l'éditeur du tenant, le filtre overridden liste chaque surcharge, ébauches automatiques comprises :

L'éditeur du tenant Physio North filtré sur ses six clés surchargées, anglais et allemand côte à côte

Étape 4 : la base change

Puis nous avons modifié un texte de base : la phrase de support anglaise est devenue « Questions? Our support team replies within one business day. », poussée avec une demande de traduction automatique, si bien que l'allemand et le français ont été retraduits. (Sans cette demande, un texte source modifié garde ses traductions et les marque à relire.) Deux tenants surchargent cette clé, un non :

  • Smile Dental (sans surcharge) a affiché la nouvelle phrase immédiatement, en allemand « Haben Sie Fragen? Unser Support-Team antwortet Ihnen innerhalb eines Werktages. », et ses fichiers sur le CDN la contenaient sans que personne ne publie le tenant (la version publie automatiquement ; sinon, le tenant est republié quand vous publiez la base).
  • Physio North et Praxis am See ont gardé leurs propres phrases. Une lecture brute (raw) du tenant (par quelqu'un qui a accès à la base) montre à côté de chaque surcharge quelle valeur de base elle remplace, si bien qu'un agent ou un script peut les comparer.

C'est la règle à retenir : les clés qu'un client n'a pas touchées suivent la base ; les clés qu'un client a modifiées restent les siennes jusqu'à ce que la surcharge soit supprimée, après quoi le tenant hérite à nouveau de la base. Les surcharges qui passent à côté d'une amélioration de la base sont le principal risque de ce schéma : quand le texte source de la base change, les traductions surchargées d'un tenant sont marquées à relire (sauf si le changement a été retraduit, comme dans cet essai), mais une surcharge dans la langue source ne reçoit aucun signal. L'éditeur du projet de base répond directement à la question « qui est concerné ? » : sélectionnez une clé et une langue, et check tenants liste les tenants que vous pouvez ouvrir qui la surchargent, avec leurs valeurs.

« Check tenants » dans l'éditeur du projet de base : la phrase de support allemande est surchargée dans 2 tenants sur 3, avec les valeurs de Physio North et de Praxis am See

Étape 5 : charger le bon client

Les fichiers publiés de chaque tenant sur le CDN combinent déjà la base et les surcharges du client : le fichier anglais de Physio North dit « Clients » et « Physio North », celui de Smile Dental « Patients » et « Smile Dental ». L'application n'a qu'à savoir quel client elle sert, d'après le sous-domaine, la connexion ou une valeur de configuration, et à transmettre l'ID de projet de ce tenant au backend :

import i18next from 'i18next'
import LocizeBackend from 'i18next-locize-backend'

// one tenant project ID per customer; customers without own wording load the base
const TENANT_PROJECT_IDS = {
  'physio-north': '<physio north tenant project id>',
  'praxis-am-see': '<praxis am see tenant project id>',
  'smile-dental': '<smile dental tenant project id>'
}
const BASE_PROJECT_ID = '<base project id>'

i18next.use(LocizeBackend).init({
  fallbackLng: 'en',
  backend: {
    projectId: TENANT_PROJECT_IDS[customer] ?? BASE_PROJECT_ID,
    version: 'latest'
  }
})

Comme les fichiers se chargent à l'exécution, la modification d'un client passe en ligne sans release de votre application ; la vitesse à laquelle les utilisateurs la voient dépend du cache, un point traité dans mettre à jour les traductions sans redéployer. Si vous embarquez plutôt les traductions, téléchargez de la même façon les fichiers de chaque tenant dans votre build.

Coût et accès

  • Plans : les tenants sont facturés avec leur projet de base. Growth en inclut 5, Professional 10, Professional Plus 20, Enterprise 50 ; au-delà, des tenants supplémentaires sont disponibles par packs (tarifs).
  • Mots : seules les valeurs surchargées comptent, si bien que les 14 clés anglaises dont Smile Dental hérite ne sont pas facturées une seconde fois.
  • Ventilation par tenant : le panneau des tenants montre aux admins une estimation de ce que vaut l'usage de chaque tenant à vos tarifs, pour répercuter les coûts sur les clients.
  • Accès : les clients peuvent travailler dans leur tenant sans se voir les uns les autres ; les membres de votre organisation ont accès à chaque tenant.

Ce qu'il faut surveiller

  • Une surcharge fige une clé pour ce client. Quand vous améliorez un texte de base, vérifiez les tenants qui le surchargent ; supprimer une surcharge rend la clé à la base.
  • Surchargez chaque langue qu'utilise un client. Une surcharge en anglais seule laisse les autres langues du tenant sur le texte de base : un client pourrait donc lire 48 heures en anglais et 24 en allemand. Les ébauches produites à partir d'une surcharge sont elles aussi des surcharges : elles comptent comme mots et ne suivent plus la base.
  • Décidez qui peut surcharger quoi. Un client qui modifie son propre tenant peut changer n'importe quelle clé, textes juridiques compris. Gardez les formulations de conformité dans la base et convenez avec les clients des clés qui leur appartiennent.
  • Langues par client. Avec « can't deviate from parent » désactivé, un tenant peut avoir des langues que la base n'a pas, et les langues ajoutées à la base ne lui sont alors pas ajoutées automatiquement. Choisissez tenant par tenant.
  • Des produits différents ne sont pas des tenants. Si les applications de deux clients ne partagent guère plus qu'un écran de connexion, des projets séparés sont plus simples.

Essayez-le

La documentation multi-tenant couvre les réglages et les options. Chaque compte démarre avec un essai de 14 jours avec toutes les fonctionnalités, sans carte bancaire, assez pour créer un projet de base et deux tenants, surcharger quelques clés et charger les fichiers de chaque client dans votre application.

Questions fréquentes

Comment donner à chaque client sa propre formulation dans une application en marque blanche ?

Gardez un seul ensemble de traductions de base et ne stockez que ce qu’un client modifie par-dessus. Dans Locize, c’est un projet tenant par client : il hérite de chaque clé et de chaque traduction du projet de base et conserve ses propres surcharges, ses propres utilisateurs et son propre ID de projet. L’application charge le tenant du client qu’elle sert ; les fichiers qu’elle reçoit combinent la base et les surcharges de ce client.

Que devient la surcharge d’un client quand le texte de base change ?

La surcharge garde sa valeur jusqu’à ce que quelqu’un la supprime dans le tenant ; le tenant hérite alors à nouveau de la valeur de base. Les clés que le client n’a pas surchargées suivent les changements de la base. Quand le texte source de la base change, les traductions surchargées du tenant sont marquées à relire (sauf si ce changement a été retraduit), mais une surcharge dans la langue source elle-même ne reçoit aucun signal : vérifiez donc les surcharges quand vous modifiez un texte de base. Dans l’éditeur Locize, « check tenants » liste les tenants que vous pouvez ouvrir qui surchargent la clé sélectionnée, avec leurs valeurs.

Comment l’application charge-t-elle les traductions du bon client ?

Chaque tenant a son propre ID de projet. L’application détermine quel client elle sert (d’après le sous-domaine, la connexion ou une valeur de configuration) et transmet l’ID de projet du tenant de ce client au backend i18next ; les clients sans formulation propre chargent le projet de base. Les fichiers sur le CDN combinent déjà la base et les surcharges, l’application n’a donc rien à fusionner.

Peut-on faire des traductions par client avec i18next seul ?

Oui, pour quelques clients : donnez à chaque client un code de langue personnalisé comme de-x-physio qui ne contient que les clés modifiées, et laissez i18next se replier sur de pour tout le reste. Cela fonctionne bien tant que les développeurs gèrent les fichiers ; cela devient lourd quand le nombre de clients multiplié par le nombre de langues augmente, car chaque combinaison est un fichier de plus et les traducteurs voient des dizaines de pseudo-langues.

Combien coûtent les tenants dans Locize ?

Les tenants sont facturés avec leur projet de base. Le plan Growth inclut 5 tenants, Professional 10, Professional Plus 20 et Enterprise 50 ; au-delà, des tenants supplémentaires sont disponibles par packs. Seules les valeurs surchargées comptent comme mots : le texte qu’un tenant hérite n’est donc pas facturé deux fois, et le panneau des tenants affiche une ventilation des coûts par tenant.

Fatigué de gérer vos traductions à la main ?

Locize est le backend de gestion de traductions créé par l'équipe i18next : diffusion CDN, traduction IA, édition in-context, sans redéploiement.

Démarrez votre essai gratuit de 14 jours