From 448fee01c4aebeb7a37e85c4d75d730a381bf5ff Mon Sep 17 00:00:00 2001 From: giancarlo Date: Tue, 23 Apr 2024 22:51:45 +0700 Subject: [PATCH] Add language priority feature flag This commit adds a new 'languagePriority' key to the feature flags configuration. It determines whether to use user's preferred language or the application's default language. Adjustments to the language selection process according to new flag have been made in the 'createInstance' function in 'i18n.server.ts'. Additionally, updates have been made to 'README.md' and '.env' files to reflect these changes. --- README.md | 22 +++-------- apps/web/.env | 3 +- apps/web/config/feature-flags.config.ts | 9 +++++ apps/web/lib/i18n/i18n.server.ts | 50 +++++++++++++++++++------ packages/monitoring/sentry/README.md | 2 +- 5 files changed, 56 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 67613d5c1..886b5333d 100644 --- a/README.md +++ b/README.md @@ -666,7 +666,7 @@ NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION=true Personal accounts are accounts that are owned by a single user. Team accounts are accounts that are owned by multiple users. This allows you to: -1. Server B2C customers (personal accounts) +1. Serve B2C customers (personal accounts) 2. Serve B2B customers (team accounts) 3. Allow both (for example, like GitHub) @@ -696,36 +696,24 @@ NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING=true To enable both, leave them both as `true`. -Please remember that for ensuring DB consistency, you need to also set them at DB level by adjusting the table `config`: - -```sql -create table if not exists public.config( - enable_team_accounts boolean default true not null, - enable_account_billing boolean default true not null, - enable_team_account_billing boolean default true not null, - billing_provider public.billing_provider default 'stripe' not null -); -``` +Please remember that to ensure DB consistency, you need to also set them at DB level by adjusting the table `config`. To enable personal account billing: ```sql -alter table public.config - set enable_account_billing to true; +update config set enable_account_billing = true; ``` To enable team account billing: ```sql -alter table public.config - set enable_team_account_billing to true; +update config set enable_team_account_billing = true; ``` To disable team accounts: ```sql -alter table public.config - set enable_team_accounts to false; +update config set enable_team_accounts = false; ``` To leave them both enabled, just leave them as they are. diff --git a/apps/web/.env b/apps/web/.env index c11631f5e..a34f2aa91 100644 --- a/apps/web/.env +++ b/apps/web/.env @@ -43,4 +43,5 @@ NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_DELETION=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS=true -NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION=true \ No newline at end of file +NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION=true +NEXT_PUBLIC_LANGUAGE_PRIORITY=application \ No newline at end of file diff --git a/apps/web/config/feature-flags.config.ts b/apps/web/config/feature-flags.config.ts index 13604b7af..e20ab81c4 100644 --- a/apps/web/config/feature-flags.config.ts +++ b/apps/web/config/feature-flags.config.ts @@ -34,6 +34,12 @@ const FeatureFlagsSchema = z.object({ required_error: 'Provide the variable NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING', }), + languagePriority: z + .enum(['user', 'application'], { + required_error: 'Provide the variable NEXT_PUBLIC_LANGUAGE_PRIORITY', + description: `If set to user, use the user's preferred language. If set to application, use the application's default language.`, + }) + .default('application'), }); const featuresFlagConfig = FeatureFlagsSchema.parse({ @@ -65,6 +71,9 @@ const featuresFlagConfig = FeatureFlagsSchema.parse({ process.env.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING, false, ), + languagePriority: process.env.NEXT_PUBLIC_LANGUAGE_PRIORITY as + | 'user' + | 'application', } satisfies z.infer); export default featuresFlagConfig; diff --git a/apps/web/lib/i18n/i18n.server.ts b/apps/web/lib/i18n/i18n.server.ts index fab05cfbc..c8b86c567 100644 --- a/apps/web/lib/i18n/i18n.server.ts +++ b/apps/web/lib/i18n/i18n.server.ts @@ -7,6 +7,7 @@ import { parseAcceptLanguageHeader, } from '@kit/i18n/server'; +import featuresFlagConfig from '~/config/feature-flags.config'; import { I18N_COOKIE_NAME, getI18nSettings, @@ -15,6 +16,12 @@ import { import { i18nResolver } from './i18n.resolver'; +/** + * @name priority + * @description The language priority setting from the feature flag configuration. + */ +const priority = featuresFlagConfig.languagePriority; + /** * @name createI18nServerInstance * @description Creates an instance of the i18n server. @@ -24,25 +31,46 @@ import { i18nResolver } from './i18n.resolver'; * Initialize the i18n instance for every RSC server request (eg. each page/layout) */ function createInstance() { - const acceptLanguage = headers().get('accept-language'); const cookie = cookies().get(I18N_COOKIE_NAME)?.value; - let language = - cookie ?? - parseAcceptLanguageHeader(acceptLanguage, languages)[0] ?? - languages[0]; + let selectedLanguage: string | undefined = undefined; + + // if the cookie is set, use the language from the cookie + if (cookie) { + selectedLanguage = getLanguageOrFallback(cookie); + } + + // if not, check if the language priority is set to user and + // use the user's preferred language + if (!selectedLanguage && priority === 'user') { + const userPreferredLanguage = getPreferredLanguageFromBrowser(); + + selectedLanguage = getLanguageOrFallback(userPreferredLanguage); + } + + const settings = getI18nSettings(selectedLanguage); + + return initializeServerI18n(settings, i18nResolver); +} + +export const createI18nServerInstance = cache(createInstance); + +function getPreferredLanguageFromBrowser() { + const acceptLanguage = headers().get('accept-language'); + + return parseAcceptLanguageHeader(acceptLanguage, languages)[0]; +} + +function getLanguageOrFallback(language: string | undefined) { + let selectedLanguage = language; if (!languages.includes(language ?? '')) { console.warn( `Language "${language}" is not supported. Falling back to "${languages[0]}"`, ); - language = languages[0]; + selectedLanguage = languages[0]; } - const settings = getI18nSettings(language); - - return initializeServerI18n(settings, i18nResolver); + return selectedLanguage; } - -export const createI18nServerInstance = cache(createInstance); diff --git a/packages/monitoring/sentry/README.md b/packages/monitoring/sentry/README.md index 34551a07c..747054ce6 100644 --- a/packages/monitoring/sentry/README.md +++ b/packages/monitoring/sentry/README.md @@ -2,7 +2,7 @@ Please set the following environment variable: -``` +```bash NEXT_PUBLIC_MONITORING_PROVIDER=sentry NEXT_PUBLIC_SENTRY_DSN=your_dsn ```