> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Aggiungi giapponese e spagnolo a un'app Next.js

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Aggiungi giapponese e spagnolo a un'app Next.js" description="Devin installa next-i18next, estrae le stringhe hardcoded in file JSON di localizzazione, aggiunge le traduzioni in giapponese e spagnolo e verifica il cambio di lingua nel browser." prompt="Aggiungi l'internazionalizzazione alla nostra app Next.js usando next-i18next. Installa next-i18next, i18next e react-i18next. Configura il routing delle lingue con defaultLocale 'en' e locales ['en', 'es', 'ja']. Analizza components/ e pages/ per tutte le stringhe inglesi hardcoded (testo JSX, placeholder, aria-label, messaggi di errore, tooltip). Crea file di localizzazione strutturati in public/locales/{en,es,ja}/common.json con chiavi suddivise per namespace. Sostituisci ogni stringa hardcoded con una chiamata a t(). Aggiungi serverSideTranslations a ogni pagina. Aggiungi un selettore della lingua alla navbar. Usa traduzioni segnaposto per spagnolo e giapponese. Avvia il server di sviluppo e testa ogni pagina in tutte e tre le lingue: controlla eventuali stringhe inglesi rimaste, overflow del layout e problemi di routing. Continua a iterare finché non funziona tutto. Non aprire una PR finché tutte e tre le lingue non vengono renderizzate correttamente su ogni pagina." category="Sviluppo di funzionalità" features="" />

<div className="uc-detail-wrapper">
  <Tip>Non vuoi configurarlo manualmente? Incolla un collegamento a questa pagina in una sessione Devin e chiedigli di configurare tutto per te.</Tip>

  <Steps>
    <Step title="(Opzionale) Imposta lo scope della codebase con Ask Devin">
      Se non sei sicuro di com'è strutturata la tua app Next.js o quali componenti contengono stringhe scritte direttamente nel codice (hardcoded), usa [Ask Devin](https://app.devin.ai/search?utm_source=docs\&utm_medium=use-case-gallery) per analizzarla preliminarmente:

      <PromptBlock agent="ada">
        ```txt Definire l'ambito del lavoro di i18n theme={null}
        Aiutami a capire l'ambito dell'aggiunta di i18n alla nostra app Next.js:
        1. Stiamo usando il Pages Router o l'App Router?
        2. Quanti componenti e pagine hanno stringhe in inglese hardcoded?
        3. Abbiamo già una configurazione di i18n o file di localizzazione?
        4. Quali componenti condivisi (pulsanti, form, modali) contengono testo?
        5. Ci sono stringhe che dovrebbero rimanere in inglese (nomi di brand, codici API)?
        ```
      </PromptBlock>

      Puoi anche avviare una sessione Devin direttamente da Ask Devin, e userà tutto ciò che ha appreso come contesto.
    </Step>

    <Step title="Avvia la configurazione dell'i18n">
      Aggiungere l’internazionalizzazione a un’app Next.js significa configurare il routing per le lingue, impostare il middleware, estrarre ogni stringa hardcoded e creare i file di traduzione — tutto questo prima ancora di poter testare anche solo un cambio di lingua. Devin gestisce l’intera pipeline: installa `next-i18next`, configura il routing delle lingue di Next.js, estrae le stringhe da decine di componenti e verifica il risultato nel browser.

      <PromptBlock>
        ```txt Add Japanese and Spanish to our Next.js app theme={null}
        Aggiungi l’internazionalizzazione alla nostra app Next.js usando next-i18next.

        - Installa next-i18next, i18next e react-i18next
        - Configura next-i18next.config.js con defaultLocale "en" e
          locales ["en", "es", "ja"]
        - Aggiorna next.config.js per includere la configurazione i18n
        - Analizza components/ e pages/ per trovare tutte le stringhe hardcoded in inglese
          (testo JSX, attributi placeholder, aria-label, messaggi di errore, tooltip)
        - Crea file di lingua strutturati in public/locales/{en,es,ja}/common.json
          con chiavi con namespace (ad es. common.save, auth.loginButton, errors.notFound)
        - Sostituisci ogni stringa hardcoded con una chiamata a t() usando useTranslation('common')
        - Aggiungi serverSideTranslations a ogni getStaticProps / getServerSideProps delle pagine
        - Aggiungi un menu a tendina per il cambio lingua a components/Navbar.tsx usando il cambio di locale di next/router
        - Usa traduzioni segnaposto per spagnolo e giapponese — inseriremo
          traduzioni professionali in un secondo momento
        - Esegui l’app e passa tra tutte e tre le lingue per confermare che non si rompa nulla

        ## Testing & verification
        - Avvia il server di sviluppo e passa tra le route /en, /es e /ja
        - Controlla ogni pagina per individuare eventuali stringhe in inglese non tradotte
        - Verifica che il selettore di lingua funzioni correttamente
        - Verifica che i valori interpolati (nomi, conteggi) vengano visualizzati correttamente in ogni lingua
        - Controlla che i layout non si rompano con stringhe spagnole più lunghe o
          caratteri giapponesi più ampi
        - Se qualcosa non funziona — traduzioni mancanti, overflow di layout,
          errori di routing — correggilo e ripeti i test. Continua a iterare finché tutte
          e tre le lingue non vengono visualizzate correttamente su ogni pagina.
        - Non aprire una PR finché non funziona tutto end-to-end
        ```
      </PromptBlock>

      Usa il comando slash **`/plan`** all’inizio della sessione così che Devin analizzi prima la tua codebase — capirà se stai usando il Pages Router o l’App Router, identificherà la libreria i18n corretta e descriverà il proprio approccio prima di scrivere qualsiasi codice. Rivedi il piano e suggerisci modifiche prima che inizi.
    </Step>

    <Step title="Come Devin gestisce la fase di configurazione">
      Devin lavora all'interno della tua codebase Next.js in modo metodico — configurando la pipeline i18n, estraendo le stringhe e creando i file di localizzazione. Ecco come funziona:

      1. **Installa le dipendenze** — esegue `npm install next-i18next i18next react-i18next` e crea i file di configurazione:

      ```js theme={null}
      // next-i18next.config.js
      module.exports = {
        i18n: {
          defaultLocale: 'en',
          locales: ['en', 'es', 'ja'],
        },
      };
      ```

      ```js theme={null}
      // next.config.js
      const { i18n } = require('./next-i18next.config');

      module.exports = {
        i18n,
        // ...la tua configurazione esistente
      };
      ```

      2. **Scansiona ogni componente** — Legge ogni file in `components/` e `pages/`, identificando il testo hardcoded in JSX, attributi come `placeholder` e `aria-label`, template literals e stringhe di errore

      3. **Genera i file di localizzazione** — Crea JSON strutturati in `public/locales/`:

      ```json theme={null}
      // public/locales/en/common.json
      {
        "common": {
          "save": "Save",
          "cancel": "Cancel",
          "loading": "Loading..."
        },
        "auth": {
          "login": "Log in",
          "signup": "Create account",
          "forgotPassword": "Forgot your password?"
        },
        "dashboard": {
          "welcome": "Welcome back, {{name}}",
          "items_one": "{{count}} item",
          "items_other": "{{count}} items"
        }
      }
      ```

      ```json theme={null}
      // public/locales/ja/common.json
      {
        "common": {
          "save": "保存",
          "cancel": "キャンセル",
          "loading": "読み込み中..."
        },
        "auth": {
          "login": "ログイン",
          "signup": "アカウント作成",
          "forgotPassword": "パスワードをお忘れですか？"
        },
        "dashboard": {
          "welcome": "おかえりなさい、{{name}}",
          "items_one": "{{count}} 件",
          "items_other": "{{count}} 件"
        }
      }
      ```

      ```json theme={null}
      // public/locales/es/common.json
      {
        "common": {
          "save": "Guardar",
          "cancel": "Cancelar",
          "loading": "Cargando..."
        },
        "auth": {
          "login": "Iniciar sesión",
          "signup": "Crear cuenta",
          "forgotPassword": "¿Olvidaste tu contraseña?"
        },
        "dashboard": {
          "welcome": "Bienvenido de nuevo, {{name}}",
          "items_one": "{{count}} elemento",
          "items_other": "{{count}} elementos"
        }
      }
      ```

      4. **Sostituisce le stringhe in-place** — Avvolge ogni componente con `useTranslation('common')` e sostituisce il testo hardcoded con chiamate a `t()`, gestendo l'interpolazione per valori dinamici come `t('dashboard.welcome', { name: user.name })`

      5. **Configura il caricamento lato server** — Aggiunge `serverSideTranslations` a ogni pagina, così che le traduzioni siano disponibili al momento del rendering:

      ```tsx theme={null}
      // pages/dashboard.tsx
      import { serverSideTranslations } from 'next-i18next/serverSideTranslations';

      export const getStaticProps = async ({ locale }) => ({
        props: {
          ...(await serverSideTranslations(locale, ['common'])),
        },
      });
      ```

      6. **Aggiunge il selettore della lingua** — Crea un menu a discesa nella barra di navigazione che utilizza il cambio di lingua del router di Next.js:

      ```tsx theme={null}
      // components/LanguageSwitcher.tsx
      import { useRouter } from 'next/router';

      export default function LanguageSwitcher() {
        const router = useRouter();

        const switchLocale = (locale: string) => {
          router.push(router.pathname, router.asPath, { locale });
        };

        return (
          <select
            value={router.locale}
            onChange={(e) => switchLocale(e.target.value)}
          >
            <option value="en">English</option>
            <option value="es">Español</option>
            <option value="ja">日本語</option>
          </select>
        );
      }
      ```
    </Step>

    <Step title="Testa e itera">
      Devin esegue `npm run dev`, apre l'app nel suo [browser integrato](/it/work-with-devin/devin-session-tools) e naviga tra le route `/en`, `/es` e `/ja` per verificare che tutto funzioni. Se qualcosa non funziona — una traduzione mancante, un layout che va oltre i bordi, una route che restituisce un 404 — Devin lo corregge e riesegue i test automaticamente.

      Usa in qualsiasi momento il comando slash **`/test`** per dire a Devin di rieseguire tutti i test e ricontrollare nel browser. Usa **`/review`** prima della PR (pull request) finale per fare in modo che Devin revisioni il proprio codice alla ricerca di stringhe mancanti, nomi di chiavi incoerenti o chiamate `serverSideTranslations` mancanti.

      Devin verifica:

      * Tutto il testo visibile è tradotto (nessuna stringa in inglese rimanente in modalità spagnolo/giapponese)
      * I layout non si rompono con stringhe spagnole più lunghe o caratteri giapponesi più larghi
      * Il selettore della lingua consente di passare tra tutte e tre le lingue/locali
      * I valori interpolati (nomi utente, conteggi) vengono visualizzati correttamente in ogni locale
      * Le regole di pluralizzazione funzionano (ad es. "1 item" → "1 件" in giapponese, "1 elemento" in spagnolo)
      * Il routing basato sulla locale di Next.js funziona — `/ja/dashboard` mostra la versione giapponese
    </Step>

    <Step title="Continua da qui">
      Una volta che la configurazione di base di i18n è pronta, procedi per estenderla.

      <PromptBlock>
        ```txt Sostituisci con traduzioni professionali theme={null}
        Sostituisci le traduzioni segnaposto in spagnolo e giapponese con queste
        traduzioni professionali fornite dal nostro vendor. [Allega i file JSON tradotti.]
        Assicurati che tutte le chiavi in public/locales/en/common.json siano coperte e
        che non rimangano segnaposto nei file es e ja.
        ```
      </PromptBlock>

      <PromptBlock>
        ```txt Aggiungi il coreano come quarta lingua theme={null}
        Aggiungi il coreano (ko) come nuova locale. Aggiorna next-i18next.config.js per includere
        "ko" nell’array locales, crea public/locales/ko/common.json con
        traduzioni segnaposto, aggiungi l’opzione al LanguageSwitcher e
        verifica che le route /ko funzionino nel browser.
        ```
      </PromptBlock>

      <PromptBlock>
        ```txt Suddividi le traduzioni per namespace di pagina theme={null}
        Il nostro common.json sta diventando troppo grande. Suddividilo in file di namespace separati:
        public/locales/{en,es,ja}/auth.json, dashboard.json e settings.json.
        Aggiorna la chiamata serverSideTranslations di ciascuna pagina per caricare solo i
        namespace di cui ha bisogno.
        ```
      </PromptBlock>
    </Step>

    <Step title="Aggiorna la configurazione del tuo repository">
      Questo task installa nuove dipendenze (`next-i18next`, `i18next`, `react-i18next`). Dopo il merge della PR, aggiorna la [configurazione dell'ambiente](/it/onboard-devin/environment) in modo che lo snapshot dell'ambiente di Devin includa questi pacchetti per le sessioni future:

      1. Vai a [**Settings > Devin's Environment > Repositories**](https://app.devin.ai/settings/machine?utm_source=docs\&utm_medium=use-case-gallery)
      2. Seleziona il tuo repo e fai clic su **Configure**
      3. In **Upkeep > Maintain dependencies**, assicurati che il comando di installazione (ad esempio `npm ci`) sia configurato
      4. Fai clic su **Save** per aggiornare lo snapshot

      Puoi anche impostare una **Upkeep Frequency** in modo che Devin riesegua automaticamente l'installazione delle dipendenze secondo una pianificazione: in questo modo lo snapshot rimane aggiornato man mano che il tuo `package.json` evolve, e le sessioni future non perdono tempo a installare pacchetti all'avvio.
    </Step>

    <Step title="Esamina la PR con Devin Review">
      Una volta che Devin ha aperto la PR, usa [Devin Review](https://app.devin.ai/review?utm_source=docs\&utm_medium=use-case-gallery) per esaminare le modifiche relative all’i18n. Devin Review può individuare stringhe hardcoded non rilevate, nomi di chiavi di traduzione incoerenti e chiamate a `serverSideTranslations` mancanti tra le varie pagine.
    </Step>
  </Steps>
</div>
