Dépannage
Chaque entrée ci-dessous correspond à un mode de défaillance réellement rencontré. Chacune indique le symptôme, la cause et la solution — la plupart se résument à l'une de ces trois causes : la phrase ne figure pas dans le projet, le SDK n'a jamais été initialisé, ou un espace réservé a été écrit pour le mauvais contexte.
Rien n’est traduit — chaque phrase reste dans la langue source
Quand tout s’affiche en texte source, c’est presque certainement que le SDK n’a pas pu s’initialiser. Il échoue en douceur par conception (votre interface ne doit jamais planter), donc le seul signal visible est la console du navigateur — consultez-la en premier. Les causes habituelles, par ordre de probabilité :
- CORS. La première requête du SDK est
authorize-project; si votre API n'autorise pas explicitement l'origine de l'application, le navigateur la bloque et l'initialisation échoue aussitôt. Rappelez-vous qu'une origine correspond exactement à schéma + hôte + port :localhost:5173etlocalhost:5174sont des origines différentes, et les serveurs de développement changent de port lorsque leur port habituel est déjà pris. Autorisez chaque port sur lequel vous développez réellement. - Identifiants incorrects. Un identifiant de projet ou une clé d'API manquant ou mal saisi fait échouer le même appel d'autorisation. La console affiche la requête en échec et son URL.
- Vous consultez la locale de base. Dans la locale de base, la « traduction » est le texte source — rien ne change visuellement. Passez à une locale cible pour tester.
# The SDK's first call is an authorize-project request.
# If the browser blocks it, NOTHING translates. Check the console for:
Access to fetch at 'https://your-api/api/authorize-project/...'
from origin 'http://localhost:5173' has been blocked by CORS policy
# Fix: allowlist the app's EXACT origin (scheme + host + port) on the API.
CORS_ALLOWED_ORIGINS=http://localhost:5173,https://app.example.com Une phrase ne se traduit pas (mais les autres, si)
La phrase dans votre code sert de clé de recherche — la phrase est la clé. Si une phrase isolée s'affiche en texte source alors que les phrases voisines sont traduites, c'est que cette clé ne figure pas dans le catalogue du projet :
- Elle n’a jamais été enregistrée. L’enregistrement passe par la découverte de tokens, et seule une clé en écriture peut l’effectuer. Si la phrase est apparue pendant que l’application tournait avec une clé en lecture seule, elle n’a jamais été envoyée nulle part : exécutez l’écran une fois en développement avec une clé en écriture, ou ajoutez la phrase dans le tableau de bord.
- Le texte a changé. Toute modification — un mot, un signe de ponctuation, même une espace — en fait une nouvelle phrase, sans aucune traduction pour l'instant. Les anciennes traductions existent toujours sous l'ancienne clé. Cela concerne particulièrement les blocs de contenu : un bloc
<Translate>est tokenisé à partir de son balisage ; modifier le texte ou la structure du bloc change donc ce qui est recherché, et le bloc revient discrètement au texte source tant que la nouvelle forme n'a pas été enregistrée et traduite. - La traduction automatique n'a pas encore suivi. Une phrase tout juste enregistrée peut avoir un petit temps de retard sur ses traductions, et une locale absente de la liste des langues cibles du projet n'en reçoit jamais. Vérifiez la phrase dans le tableau de bord : est-elle enregistrée ? traduite dans cette locale ?
Pourquoi les phrases manquantes ne génèrent-elles pas d'erreur ?
C'est voulu. En production, un système de traduction doit se dégrader vers un texte source lisible, jamais vers une page cassée — ainsi, une phrase non enregistrée s'affiche dans sa version source et le SDK reste silencieux. Revers de la médaille : avec une clé en lecture seule, une phrase manquante est silencieuse. Rien n'est journalisé, rien n'est enregistré, et vous ne l'apprenez que lorsqu'un utilisateur voit de l'anglais. Ce qui l'évite, c'est la séparation des clés : développez avec une clé d'écriture pour que chaque phrase affichée par votre interface soit découverte, puis déployez en lecture seule.
# Development — write key: new phrases are discovered,
# registered, and machine-translated as you build.
VITE_LANGSYS_API_KEY=write-key
# Production — read-only key: fetches the finished catalog only.
# Unregistered phrases silently render their source text.
VITE_LANGSYS_API_KEY=read-only-key Mon espace réservé s'affiche tel quel — « Hi %name% » ou « Hi {name} »
- Dans les appels
t(), les espaces réservés s'écrivent avec une seule accolade{name}, et l'interpolation ne s'exécute que si vous passez les paramètres :t('Hello, {name}!', 'Greetings', { name }). - Dans le balisage
<Translate>/<Phrase>sous React, Vue ou Svelte, écrivez les espaces réservés sous la forme%name%. Le compilateur du framework interprète une expression{name}nue comme une expression avant même que le SDK ne la voie ;%name%survit à la compilation et le SDK la normalise en{name}lors de la capture. La forme simple{name}convient en HTML pur, où aucune syntaxe de template n’entre en conflit. - Des paramètres manquants ? Si aucun
paramsn'est fourni, le modèle est affiché tel quel : c'est le%name%littéral que vous voyez.
Ça fonctionne, puis ça se casse après plusieurs changements de locale successifs
Mettez à jour le SDK. Voici de vrais bugs corrigés dans ce domaine : le retour à la locale initiale/SSR laissait le catalogue précédent actif (corrigé dans langsys-js-typescript 0.2.2), et les consommateurs de Translate/Phrase en mode bloc de contenu pouvaient se bloquer indéfiniment sur un catalogue initialisé côté serveur (corrigé dans la 0.2.3). Si vous voyez des chaînes dans une ancienne locale ou des blocs qui ne se résolvent jamais, comparez votre version installée avec le journal des modifications du SDK de base avant de déboguer votre propre code.
Côté serveur : la page renvoie une erreur 500 au lieu de se dégrader en douceur
Le client du SDK PHP génère une exception s'il est construit sans identifiants : une application Laravel (ou PHP standard) dont LANGSYS_API_KEY est vide échoue donc dès la résolution du conteneur, avant toute traduction. Définissez les identifiants (ou, pour une application qui doit pouvoir démarrer sans eux, liez un client factice comme le font les applications de démo). Une fois les identifiants en place, les échecs de l'API à l'exécution se dégradent en douceur : si l'API est injoignable ou refuse la requête, le texte source est affiché et l'exception est signalée, sans jamais faire tomber la page.
Côté serveur : la première requête se bloque, puis tout est rapide
Le délai d’expiration HTTP du SDK PHP est de 30 secondes, et une instance d’API qui sort de veille peut s’en approcher dès le tout premier appel. Cette requête soit aboutit lentement (et réchauffe le cache du catalogue — tout ce qui suit est servi depuis le cache), soit expire et affiche le texte source. Si le premier chargement de page après une période d’inactivité est lent, c’est la raison : c’est l’API qui se réchauffe, pas votre intégration.
Côté serveur : j’ai effectué le rendu avec une clé d’écriture, mais la phrase n’apparaît pas dans le tableau de bord
Les phrases découvertes sont mises en file d'attente pendant la requête et envoyées après l'envoi de la réponse — c'est le middleware terminable de Laravel. Actualisez le tableau de bord un instant après le chargement de la page, et non pendant. Sur les environnements d'exécution de workers persistants (Octane, FrankenPHP, RoadRunner), assurez-vous d'utiliser l'intégration fournie par le SDK : le hook d'arrêt PHP standard n'est jamais déclenché entre deux requêtes d'un worker.
Rendu côté serveur : les traductions d'une requête se retrouvent dans une autre
Le SDK JS de base ne conserve que le catalogue d'une seule locale à la fois : c'est un singleton au niveau du module. Un serveur Node qui génère des locales différentes pour des requêtes simultanées va se heurter à des conflits d'accès. Récupérez le catalogue à chaque requête et initialisez le client avec celui-ci, comme dans les guides Next.js, Nuxt et SvelteKit, ou exécutez une locale par processus.
Toujours bloqué ? Ouvrez un ticket sur le dépôt du SDK — typescript, react, vue, svelte, php ou laravel — en joignant la sortie de la console (ou le journal du serveur) de la requête en échec. Vous pouvez aussi écrire à [email protected].