next.jstranslationi18nextnext-intl

Loading Translation Files from a Server or CMS in next-intl - Seeking Guidance


I'm looking for a solution to load translation files directly from a server or a Content Management System (CMS) in next-intl, rather than relying on local translation files. Currently, the documentation recommends importing translation files from the messages directory, as demonstrated in this code snippet:

i18n.ts

import {getRequestConfig} from 'next-intl/server';
 
export default getRequestConfig(async ({locale}) => ({
  messages: (await import(`./messages/${locale}.json`)).default
}));

However, this approach poses challenges when it comes to correcting translation errors or making updates since it requires changes to project files and website redeployment. Is there a method to fetch translations directly from the server or a CMS? I've seen videos mentioning this capability, but I haven't found any relevant documentation.

I attempted the following approach, but it didn't yield the desired results:

import {getRequestConfig} from 'next-intl/server';
 
export default getRequestConfig(async ({locale}) => ({

    messages: (fetch(`apiendpoint/${locale}`).then(res => res.json()).then(res => res.data)
    )

}));

Could someone please provide guidance on how to load translations from a server in next-intl, or point me in the right direction if there's documentation or resources available for this specific feature? Your assistance would be greatly appreciated.


Solution

  • You're doing it well, but you forgot to await the promise.

    Your code:

    import {getRequestConfig} from 'next-intl/server';
     
    export default getRequestConfig(async ({locale}) => ({
        messages: (fetch(`apiendpoint/${locale}`).then(res => res.json()).then(res => res.data)
        )
    }));
    

    Not the right side type ((fetch(apiendpoint/${locale}).then(res => res.json()).then(res => res.data)) is Promise<any> but messages expect to receive IntlMessages.

    Try this instead:

    export default getRequestConfig(async ({locale}) => ({
    
        messages: (await fetch(`apiendpoint/${locale}`).then(res => res.json()).then(res => res.data)
        )
    }));
    

    This code looks unorganized, so let's format it:

    export default getRequestConfig(async ({locale}) => {
        const res = await fetch(endpoint)
        const data = await res.json()
        // Now, (data) is the json data returned from the api
        // try to console.log it to see if it contains data.data
        const messages = data.data
        
        return {
           messages
        }
    })