-
-
Notifications
You must be signed in to change notification settings - Fork 764
Replies: 3 comments · 54 replies
-
@adrai, could you help me with this issue, please? |
Beta Was this translation helpful? Give feedback.
All reactions
-
I am able now to deploy my app, but when I was testing if scoped ns working in real production env, it did not seem to work as expected, still, a conflict happens, I need to reload the page 2/3 times to see the correct tenant translations and when I open another tenant site and reload the page I will see the translation from tenant 1 until a new page reload I will see the correct translations but on tenant 1 the translations will also be wrong, and it will get them from the prev tenant. even my API backend returns the correct translations is there any way please I could get your help debugging the issue in my production project? |
Beta Was this translation helpful? Give feedback.
All reactions
-
This sounds to be Next.js internal/specific behaviours... so best would be you ask the Vercel/Next.js team for help |
Beta Was this translation helpful? Give feedback.
All reactions
-
I made some debugging to understand more about what is happening, the issue seems to be with i18next backend,
namespaces after I get them from const groupArr = ns.split("+"); //[ 'common=1', 'validation=1', 'auth=1', 'otp=1' ] until now everything is working fine, but when I open tenant 2 site:
the namespaces here have different key which is 2 not 1 (different namespace) BUT HERE IS THE ISSUE: when I get namespaces from
the namespaces received from the request method are not updated, they are cached from the previously sent request |
Beta Was this translation helpful? Give feedback.
All reactions
-
Who responds to the request? Isn't that your axios request that goes to /translations ? which "server" logic responds there? |
Beta Was this translation helpful? Give feedback.
All reactions
-
SORRY, the logs are too long, server log when tenant 1 sends request: serverSideTranslations namespaces [ 'common=1', 'validation=1', 'auth=1', 'otp=1' ]
i18next: languageChanged ar
i18next: initialized {
debug: true,
initImmediate: undefined,
ns: [],
defaultNS: 'common',
fallbackLng: [ 'ar' ],
fallbackNS: false,
supportedLngs: false,
nonExplicitSupportedLngs: false,
load: 'currentOnly',
preload: [ 'ar', 'en' ],
simplifyPluralSuffix: true,
keySeparator: '.',
nsSeparator: ':',
pluralSeparator: '_',
contextSeparator: '_',
partialBundledLanguages: false,
saveMissing: false,
updateMissing: false,
saveMissingTo: 'fallback',
saveMissingPlurals: true,
missingKeyHandler: false,
missingInterpolationHandler: false,
postProcess: false,
postProcessPassResolved: false,
returnNull: true,
returnEmptyString: true,
returnObjects: false,
joinArrays: false,
returnedObjectHandler: false,
parseMissingKeyHandler: false,
appendNamespaceToMissingKey: false,
appendNamespaceToCIMode: false,
overloadTranslationOptionHandler: [Function: handle],
interpolation: {
escapeValue: false,
format: [Function: bound format],
prefix: '{{',
suffix: '}}',
formatSeparator: ',',
unescapePrefix: '-',
nestingPrefix: '$t(',
nestingSuffix: ')',
nestingOptionsSeparator: ',',
maxReplaces: 1000,
skipOnVariables: true
},
errorStackTraceLimit: 0,
localeExtension: 'json',
localePath: './public/locales',
localeStructure: '{{lng}}/{{ns}}',
react: { useSuspense: false },
reloadOnPrerender: true,
serializeConfig: false,
use: [ [Function: Backend] { type: 'backend' } ],
maxParallelReads: 30,
backend: {
backend: [Function: Backend] { type: 'backend' },
backendOption: {
loadPath: '{{lng}}|{{ns}}',
customHeaders: [Object],
request: [AsyncFunction: request],
addPath: '/locales/add/{{lng}}/{{ns}}',
allowMultiLoading: false,
parse: [Function: parse],
stringify: [Function: stringify],
parsePayload: [Function: parsePayload],
parseLoadPayload: [Function: parseLoadPayload],
reloadInterval: 3600000,
queryStringParams: {},
crossDomain: false,
withCredentials: false,
overrideMimeType: false,
requestOptions: [Object]
},
debounceInterval: 50
},
lng: 'ar',
defaultLocale: 'ar',
locales: [ 'ar', 'en' ],
ignoreJSONStructure: true
}
request->url: [ 'common=1', 'validation=1', 'auth=1', 'otp=1' ]
ns after removing cache key to send them to back end: [ 'common', 'validation', 'auth', 'otp' ]
cacheKey: 1
axios request response data:
{
ar: {
auth: {
welcome_back: 'sign in Tenant 1',
welcome_back_description: 'welcome back! Tenant 1',
welcome_back_description_email_only: 'welcome back! Tenant 1',
login_via: 'Log in via: Tenant 1'
},
otp: {
verify_email: 'verify your e-mail Tenant 1',
verify_email_description: 'A text message was sent to {{email}}. Tenant 1',
change_email: 'Change email Tenant 1'
},
common: {
save: 'save Tenant 1',
delete: 'delete Tenant 1',
edit: 'amendment Tenant 1',
an_hour: 'hour Tenant 1',
a_minute: 'minute Tenant 1',
a_day: 'today Tenant 1'
},
validation: {
field_required: 'This field is required Tenant 1',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 1',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 1',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 1',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 1',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 1'
}
}
}
after adding cache key again and passing the data to the callback:
{
ar: {
'auth=1': {
welcome_back: 'sign in Tenant 1',
welcome_back_description: 'welcome back! Tenant 1',
welcome_back_description_email_only: 'welcome back! Tenant 1',
login_via: 'Log in via: Tenant 1'
},
'otp=1': {
verify_email: 'verify your e-mail Tenant 1',
verify_email_description: 'A text message was sent to {{email}}. Tenant 1',
change_email: 'Change email Tenant 1'
},
'common=1': {
save: 'save Tenant 1',
delete: 'delete Tenant 1',
edit: 'amendment Tenant 1',
an_hour: 'hour Tenant 1',
a_minute: 'minute Tenant 1',
a_day: 'today Tenant 1'
},
'validation=1': {
field_required: 'This field is required Tenant 1',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 1',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 1',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 1',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 1',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 1'
}
}
}
i18next::backendConnector: loaded namespace common=1 for language ar {
save: 'save Tenant 1',
delete: 'delete Tenant 1',
edit: 'amendment Tenant 1',
an_hour: 'hour Tenant 1',
a_minute: 'minute Tenant 1',
a_day: 'today Tenant 1'
}
i18next::backendConnector: loaded namespace validation=1 for language ar {
field_required: 'This field is required Tenant 1',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 1',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 1',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 1',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 1',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 1',
field_min_length: 'The field must be at least {{min}} Letter(s). Tenant 1'
}
i18next::backendConnector: loaded namespace auth=1 for language ar {
welcome_back: 'sign in Tenant 1',
welcome_back_description: 'welcome back! Tenant 1',
welcome_back_description_email_only: 'welcome back! Tenant 1',
login_via: 'Log in via: Tenant 1'
}
i18next::backendConnector: loaded namespace otp=1 for language ar {
verify_email: 'verify your e-mail Tenant 1',
verify_email_description: 'A text message was sent to {{email}}. Tenant 1',
change_email: 'Change email Tenant 1'
}
i18next::backendConnector: loaded namespace common=1 for language en {}
i18next::backendConnector: loaded namespace validation=1 for language en {}
i18next::backendConnector: loaded namespace auth=1 for language en {}
i18next::backendConnector: loaded namespace otp=1 for language en {}
i18next: languageChanged ar
i18next::translator: missingKey ar validation=1 field_invalid field_invalid
i18next::translator: missingKey ar validation=1 field_invalid_format field_invalid_format the same logs I get when open tenant 2 sends the request but only the cache key is different instead of 1 it is 2 and its working as expected so I will not provide it server log when tenant 1 sends request after revisit and reload: serverSideTranslations namespaces [ 'common=2', 'validation=2', 'auth=2', 'otp=2' ]
request->url:: [ 'common=1', 'validation=1', 'auth=1', 'otp=1' ]
ns after removing cache key to send them to back end:: [ 'common', 'validation', 'auth', 'otp' ]
cacheKey: 1
axios request response data:
{
ar: {
auth: {
welcome_back: 'sign in Tenant 2',
welcome_back_description: 'welcome back! Tenant 2',
welcome_back_description_email_only: 'welcome back! Tenant 2',
login_via: 'Log in via: Tenant 2'
},
otp: {
verify_email: 'verify your e-mail Tenant 2',
verify_email_description: 'A text message was sent to {{email}}. Tenant 2',
change_email: 'Change email Tenant 2'
},
common: {
save: 'save Tenant 2',
delete: 'delete Tenant 2',
edit: 'amendment Tenant 2',
an_hour: 'hour Tenant 2',
a_minute: 'minute Tenant 2',
a_day: 'today Tenant 2'
},
validation: {
field_required: 'This field is required Tenant 2',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 2',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 2',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 2',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 2',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 2'
}
}
}
after adding cache key again and passing the data to the callback:
{
ar: {
'auth=1': {
welcome_back: 'sign in Tenant 2',
welcome_back_description: 'welcome back! Tenant 2',
welcome_back_description_email_only: 'welcome back! Tenant 2',
login_via: 'Log in via: Tenant 2'
},
'otp=1': {
verify_email: 'verify your e-mail Tenant 2',
verify_email_description: 'A text message was sent to {{email}}. Tenant 2',
change_email: 'Change email Tenant 2'
},
'common=1': {
save: 'save Tenant 2',
delete: 'delete Tenant 2',
edit: 'amendment Tenant 2',
an_hour: 'hour Tenant 2',
a_minute: 'minute Tenant 2',
a_day: 'today Tenant 2'
},
'validation=1': {
field_required: 'This field is required Tenant 2',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 2',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 2',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 2',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 2',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 2'
}
}
}
i18next::backendConnector: loaded namespace common=1 for language ar {
save: 'save Tenant 2',
delete: 'delete Tenant 2',
edit: 'amendment Tenant 2',
an_hour: 'hour Tenant 2',
a_minute: 'minute Tenant 2',
a_day: 'today Tenant 2'
}
i18next::backendConnector: loaded namespace validation=1 for language ar {
field_required: 'This field is required Tenant 2',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 2',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 2',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 2',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 2',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 2'
}
i18next::backendConnector: loaded namespace auth=1 for language ar {
welcome_back: 'sign in Tenant 2',
welcome_back_description: 'welcome back! Tenant 2',
welcome_back_description_email_only: 'welcome back! Tenant 2',
login_via: 'Log in via: Tenant 2'
}
i18next::backendConnector: loaded namespace otp=1 for language ar {
verify_email: 'verify your e-mail Tenant 2',
verify_email_description: 'A text message was sent to {{email}}. Tenant 2',
change_email: 'Change email Tenant 2'
} i18next log from clinet for tenant 1: {
debug: true,
initImmediate: true,
ns: ["common=1", "validation=1", "auth=1", "otp=1"],
defaultNS: "common",
fallbackLng: ["ar"],
fallbackNS: false,
supportedLngs: false,
nonExplicitSupportedLngs: false,
load: "currentOnly",
preload: false,
simplifyPluralSuffix: true,
keySeparator: ".",
nsSeparator: ":",
pluralSeparator: "_",
contextSeparator: "_",
partialBundledLanguages: false,
saveMissing: false,
updateMissing: false,
saveMissingTo: "fallback",
saveMissingPlurals: true,
missingKeyHandler: false,
missingInterpolationHandler: false,
postProcess: false,
postProcessPassResolved: false,
returnNull: true,
returnEmptyString: true,
returnObjects: false,
joinArrays: false,
returnedObjectHandler: false,
parseMissingKeyHandler: false,
appendNamespaceToMissingKey: false,
appendNamespaceToCIMode: false,
interpolation: {
escapeValue: false,
prefix: "{{",
suffix: "}}",
formatSeparator: ",",
unescapePrefix: "-",
nestingPrefix: "$t(",
nestingSuffix: ")",
nestingOptionsSeparator: ",",
maxReplaces: 1000,
skipOnVariables: true
},
errorStackTraceLimit: 0,
localeExtension: "json",
localePath: "./public/locales",
localeStructure: "{{lng}}/{{ns}}",
react: {
useSuspense: false
},
reloadOnPrerender: true,
serializeConfig: false,
use: [null],
maxParallelReads: 30,
backend: {
backendOption: {
loadPath: "{{lng}}|{{ns}}",
customHeaders: {},
addPath: "/locales/add/{{lng}}/{{ns}}",
allowMultiLoading: false,
reloadInterval: false,
queryStringParams: {},
crossDomain: false,
withCredentials: false,
overrideMimeType: false,
requestOptions: {
mode: "cors",
credentials: "same-origin",
cache: "default"
}
},
debounceInterval: 50
},
lng: "ar",
defaultLocale: "ar",
locales: ["ar", "en"],
resources: {
ar: {
"common=1": {
save: "save Tenant 2",
delete: "delete Tenant 2",
edit: "amendment Tenant 2",
an_hour: "hour Tenant 2",
a_minute: "minute Tenant 2",
a_day: "today Tenant 2"
},
"validation=1": {
field_required: "This field is required Tenant 2",
field_file_size_invalid: "File size must be less than {{size}} MB Tenant 2",
field_file_type_invalid: "The file must be of type {{type}} Tenant 2",
field_file_min_files: "Must download {{files}} File(s) at least Tenant 2",
field_file_max_files: "Must download {{files}} File(s) at most Tenant 2",
field_invalid_slug_format: "The link can contain only English or Arabic letters, numbers, or - Tenant 2"
},
"auth=1": {
welcome_back: "sign in Tenant 2",
welcome_back_description: "welcome back! Tenant 2",
welcome_back_description_email_only: "welcome back! Tenant 2",
login_via: "Log in via: Tenant 2"
},
"otp=1": {
verify_email: "verify your e-mail Tenant 2",
verify_email_description: "A text message was sent to {{email}}. Tenant 2",
change_email: "Change email Tenant 2"
}
}
},
ignoreJSONStructure: true
}; tenant 2: {
debug: true,
initImmediate: true,
ns: ["common=2", "validation=2", "auth=2", "otp=2"],
defaultNS: "common",
fallbackLng: ["ar"],
fallbackNS: false,
supportedLngs: false,
nonExplicitSupportedLngs: false,
load: "currentOnly",
preload: false,
simplifyPluralSuffix: true,
keySeparator: ".",
nsSeparator: ":",
pluralSeparator: "_",
contextSeparator: "_",
partialBundledLanguages: false,
saveMissing: false,
updateMissing: false,
saveMissingTo: "fallback",
saveMissingPlurals: true,
missingKeyHandler: false,
missingInterpolationHandler: false,
postProcess: false,
postProcessPassResolved: false,
returnNull: true,
returnEmptyString: true,
returnObjects: false,
joinArrays: false,
returnedObjectHandler: false,
parseMissingKeyHandler: false,
appendNamespaceToMissingKey: false,
appendNamespaceToCIMode: false,
interpolation: {
escapeValue: false,
prefix: "{{",
suffix: "}}",
formatSeparator: ",",
unescapePrefix: "-",
nestingPrefix: "$t(",
nestingSuffix: ")",
nestingOptionsSeparator: ",",
maxReplaces: 1000,
skipOnVariables: true
},
errorStackTraceLimit: 0,
localeExtension: "json",
localePath: "./public/locales",
localeStructure: "{{lng}}/{{ns}}",
react: {
useSuspense: false
},
reloadOnPrerender: true,
serializeConfig: false,
use: [null],
maxParallelReads: 30,
backend: {
backendOption: {
loadPath: "{{lng}}|{{ns}}",
customHeaders: {},
addPath: "/locales/add/{{lng}}/{{ns}}",
allowMultiLoading: false,
reloadInterval: false,
queryStringParams: {},
crossDomain: false,
withCredentials: false,
overrideMimeType: false,
requestOptions: {
mode: "cors",
credentials: "same-origin",
cache: "default"
}
},
debounceInterval: 50
},
lng: "ar",
defaultLocale: "ar",
locales: ["ar", "en"],
resources: {
ar: {
"common=2": {
save: "save Tenant 2",
delete: "delete Tenant 2",
edit: "amendment Tenant 2",
an_hour: "hour Tenant 2",
a_minute: "minute Tenant 2",
a_day: "today Tenant 2"
},
"validation=2": {
field_required: "This field is required Tenant 2",
field_file_size_invalid: "File size must be less than {{size}} MB Tenant 2",
field_file_type_invalid: "The file must be of type {{type}} Tenant 2",
field_file_min_files: "Must download {{files}} File(s) at least Tenant 2",
field_file_max_files: "Must download {{files}} File(s) at most Tenant 2",
field_invalid_slug_format: "The link can contain only English or Arabic letters, numbers, or - Tenant 2"
},
"auth=2": {
welcome_back: "sign in Tenant 2",
welcome_back_description: "welcome back! Tenant 2",
welcome_back_description_email_only: "welcome back! Tenant 2",
login_via: "Log in via: Tenant 2"
},
"otp=2": {
verify_email: "verify your e-mail Tenant 2",
verify_email_description: "A text message was sent to {{email}}. Tenant 2",
change_email: "Change email Tenant 2"
}
}
},
ignoreJSONStructure: true
}; |
Beta Was this translation helpful? Give feedback.
All reactions
-
serverSideTranslations passes =2 |
Beta Was this translation helpful? Give feedback.
All reactions
-
Also, you could try to "remove" the serverSideTranslations call completely and return something hardcoded... something for tenant1 and something different for tenant2... and check if the same problem occurs... That way we could make sure this is not at all related to next-i18next |
Beta Was this translation helpful? Give feedback.
All reactions
-
btw: in the next.js discussion, you may want to say this is only occurring on your deployed environment |
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
fyi: it may also be Forge is caching something... |
Beta Was this translation helpful? Give feedback.
All reactions
-
👀 1
-
followed the same scenario mentioned previously: server log returned from serverSideTranslations when tenant 1 sends request: {
_nextI18Next: {
initialI18nStore: {
ar: {
'common=1': {
save: 'save Tenant 1',
delete: 'delete Tenant 1',
edit: 'amendment Tenant 1',
an_hour: 'hour Tenant 1',
a_minute: 'minute Tenant 1',
a_day: 'today Tenant 1'
},
'validation=1': {
field_required: 'This field is required Tenant 1',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 1',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 1',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 1',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 1',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 1'
},
'auth=1': {
welcome_back: 'sign in Tenant 1',
welcome_back_description: 'welcome back! Tenant 1',
welcome_back_description_email_only: 'welcome back! Tenant 1'
},
'otp=1': {
verify_email: 'verify your e-mail Tenant 1',
verify_email_description: 'A text message was sent to {{email}}. Tenant 1',
change_email: 'Change email Tenant 1'
}
}
},
initialLocale: 'ar',
ns: [ 'common=1', 'validation=1', 'auth=1', 'otp=1' ],
userConfig: null
}
} the same returned logs I get when open tenant 2 sends the request but only the cache key is different instead of 1 it is 2 and its working as expected so I will not provide it server log returned from serverSideTranslations when tenant 1 sends request after revisit and reload: {
_nextI18Next: {
initialI18nStore: {
ar: {
'common=1': {
save: 'save Tenant 2',
delete: 'delete Tenant 2',
edit: 'amendment Tenant 2',
an_hour: 'hour Tenant 2',
a_minute: 'minute Tenant 2',
a_day: 'today Tenant 2'
},
'validation=1': {
field_required: 'This field is required Tenant 2',
field_file_size_invalid: 'File size must be less than {{size}} MB Tenant 2',
field_file_type_invalid: 'The file must be of type {{type}} Tenant 2',
field_file_min_files: 'Must download {{files}} File(s) at least Tenant 2',
field_file_max_files: 'Must download {{files}} File(s) at most Tenant 2',
field_invalid_slug_format: 'The link can contain only English or Arabic letters, numbers, or - Tenant 2'
},
'auth=1': {
welcome_back: 'sign in Tenant 2',
welcome_back_description: 'welcome back! Tenant 2',
welcome_back_description_email_only: 'welcome back! Tenant 2',
login_via: 'Log in via: Tenant 2'
},
'otp=1': {
verify_email: 'verify your e-mail Tenant 2',
verify_email_description: 'A text message was sent to {{email}}. Tenant 2',
change_email: 'Change email Tenant 2'
}
}
},
initialLocale: 'ar',
ns: [ 'common=1', 'validation=1', 'auth=1', 'otp=1' ],
userConfig: null
}
} and when I tried to hardcoded the locals object, following the same scenario first load tenant 1 everything worked as expected, when tried to load tenant 2, I got a Hydration error, and then locals for tenant 2 appeared, then back to tenant 1 reloaded the page everything worked the translations for tenant 1. Screen.Recording.2024-02-01.at.11.32.03.PM.movI think it is related to |
Beta Was this translation helpful? Give feedback.
All reactions
-
I tried to disable Next.js cache completely in res.setHeader("Cache-Control", "no-store"); and still the same issue, the url param in request method is still passed from the prev requested resources |
Beta Was this translation helpful? Give feedback.
All reactions
-
@adrai. Hi again, I have disabled I was doing some research and I found out locize has support for multi-tenant: https://docs.locize.com/more/multi-tenant |
Beta Was this translation helpful? Give feedback.
All reactions
-
A post processor will never load different namespaces etc.... |
Beta Was this translation helpful? Give feedback.
All reactions
-
thanks a lot for clarifying how i18next and locize handle multi-tenant setups. and I agree with you we are back to the start and I have to think differently. I was wondering if you'd be open to helping us implement this directly in the project? We're totally on board with it being a paid consulting session. Alternatively, does locize offer something like this as a service? We're open to outsourcing this task to get it right. Looking forward to your thoughts and I hope you accept helping us! |
Beta Was this translation helpful? Give feedback.
All reactions
-
No, unfortunately I can't help you with that. And locize does also not offer this type of services. Sorry. |
Beta Was this translation helpful? Give feedback.
All reactions
-
ok, understand, so could you tell me more about what you mean by this? |
Beta Was this translation helpful? Give feedback.
All reactions
-
Like you need a separate Next.js App per each tenant... so a lot of individual next.js apps... |
Beta Was this translation helpful? Give feedback.
-
Hello, I am currently working on a multi-tenant application. The content of each tenant is served based on the host, which is set as a header in each request sent to the API. Here’s a snippet of my code:
but I’m facing a caching issue in
next-i18next
. If any tenant updates a translation key, the changes are not reflected until I manually restart the server.another issue is that if
Tenant1
updates a key and sends the very first request to the server after a restart,i18next
caches the translations based onTenant1
. Now, ifTenant2
opens their site, they see the updated values fromTenant1
, which is not the expected behavior.Here’s a step-by-step breakdown of the issue:
Tenant1
updates a translation key.Tenant1
changes are not reflected until the server is manually restarted.Tenant2
accesses the site, they seeTenant1
updated translations.here is what my setup looks like:
_app.tsx
:in each page's
getServerSideProps
:next-i18next.config.js
:I could try to set
reloadOnPrerender
totrue
but it will cause deadly memory issues.and I can not use
revalidate
option ingetStaticProps
because I am not building anISR
app and in my application, I am I have to usegetServerSideProps
for data fetching.I would appreciate any guidance on how to resolve this issue. Thank you!
Beta Was this translation helpful? Give feedback.
All reactions