-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Implement Internationalization (en and fr) for Multi-language Support #485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 25 commits
f1c61e6
7560e16
62ccfdb
6dae8b1
ec5e1f0
c67daa9
20498ec
778d307
2b0a5dd
bb3e449
6f25a0a
ca3e01c
ecd5c9a
3418b9a
b2300c7
4194541
71cd197
9e09bd1
318a58e
63fa13a
a816afb
6b4b98d
85917a1
f284eb1
d8e4b76
a8ec4b0
d84767e
feb18b4
da1ff45
26c238c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,14 @@ | ||
| import {Metadata} from "next"; | ||
| import { useTranslations } from "next-intl"; | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: 'Error', | ||
| description: '', | ||
| } | ||
|
|
||
| export default async function Page() { | ||
| const t= useTranslations('Error') | ||
| return ( | ||
| <div>We are experiencing some difficulty, try to refresh the page</div> | ||
| <div>{t("errorMsg")}</div> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,29 +4,31 @@ import { FC, useCallback, useState } from 'react'; | |||||||||||||||||||||||||||||||||||||||
| import clsx from 'clsx'; | ||||||||||||||||||||||||||||||||||||||||
| import interClass from '@gitroom/react/helpers/inter.font'; | ||||||||||||||||||||||||||||||||||||||||
| import { useVariables } from '@gitroom/react/helpers/variable.context'; | ||||||||||||||||||||||||||||||||||||||||
| import { useTranslations } from 'next-intl'; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const useFaqList = () => { | ||||||||||||||||||||||||||||||||||||||||
| const {isGeneral} = useVariables(); | ||||||||||||||||||||||||||||||||||||||||
| const t = useTranslations('Billing') | ||||||||||||||||||||||||||||||||||||||||
| return [ | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| title: `Can I trust ${isGeneral ? 'Postiz' : 'Gitroom'}?`, | ||||||||||||||||||||||||||||||||||||||||
| description: `${isGeneral ? 'Postiz' : 'Gitroom'} is proudly open-source! We believe in an ethical and transparent culture, meaning that ${isGeneral ? 'Postiz' : 'Gitroom'} will live forever. You can check out the entire code or use it for personal projects. To view the open-source repository, <a href="https://github.com/gitroomhq/postiz-app" target="_blank" style="text-decoration: underline;">click here</a>.`, | ||||||||||||||||||||||||||||||||||||||||
| title: t('trust_title', {product: isGeneral ? 'Postiz' : 'Gitroom'}), | ||||||||||||||||||||||||||||||||||||||||
| description: t('trust_description', { | ||||||||||||||||||||||||||||||||||||||||
| product: isGeneral ? 'Postiz' : 'Gitroom', | ||||||||||||||||||||||||||||||||||||||||
| repoLink: '<a href="https://github.com/gitroomhq/postiz-app" target="_blank" style="text-decoration: underline;">', | ||||||||||||||||||||||||||||||||||||||||
| repoLinkEnd: '</a>' | ||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security: Ensure HTML in translations is properly sanitized The use of
Example safer approach: - description: t('trust_description', {
- product: isGeneral ? 'Postiz' : 'Gitroom',
- repoLink: '<a href="https://github.com/gitroomhq/postiz-app" target="_blank" style="text-decoration: underline;">',
- repoLinkEnd: '</a>'
- }),
+ description: (
+ <>
+ {t('trust_description_start', { product: isGeneral ? 'Postiz' : 'Gitroom' })}
+ <a
+ href="https://github.com/gitroomhq/postiz-app"
+ target="_blank"
+ rel="noopener noreferrer"
+ style={{ textDecoration: 'underline' }}
+ >
+ {t('trust_description_link')}
+ </a>
+ {t('trust_description_end')}
+ </>
+ )📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| title: 'What are channels?', | ||||||||||||||||||||||||||||||||||||||||
| description: `${ | ||||||||||||||||||||||||||||||||||||||||
| isGeneral ? 'Postiz' : 'Gitroom' | ||||||||||||||||||||||||||||||||||||||||
| } allows you to schedule your posts between different channels. | ||||||||||||||||||||||||||||||||||||||||
| A channel is a publishing platform where you can schedule your posts. | ||||||||||||||||||||||||||||||||||||||||
| For example, you can schedule your posts on X, Facebook, Instagram, TikTok, YouTube, Reddit, Linkedin, Dribbble, Threads and Pinterest.`, | ||||||||||||||||||||||||||||||||||||||||
| title: t('What are channels?'), | ||||||||||||||||||||||||||||||||||||||||
| description: t('channels_answer?', {product: isGeneral ? 'Postiz' : 'Gitroom'}) | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+33
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Standardize translation key format The translation keys use inconsistent formats:
This makes maintenance harder and could cause issues with translation management. Standardize to a consistent format, preferably using dot notation and meaningful keys: - title: t('What are channels?'),
- description: t('channels_answer?', {product: isGeneral ? 'Postiz' : 'Gitroom'})
+ title: t('faq.channels.title'),
+ description: t('faq.channels.description', {product: isGeneral ? 'Postiz' : 'Gitroom'})Also applies to: 37-38, 41-42 |
||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| title: 'What are team members?', | ||||||||||||||||||||||||||||||||||||||||
| description: `If you have a team with multiple members, you can invite them to your workspace to collaborate on your posts and add their personal channels`, | ||||||||||||||||||||||||||||||||||||||||
| title: t('What are team members?'), | ||||||||||||||||||||||||||||||||||||||||
| description: t(`If you have a team with multiple members, you can invite them to your workspace to collaborate on your posts and add their personal channels`), | ||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| title: 'What is AI auto-complete?', | ||||||||||||||||||||||||||||||||||||||||
| description: `We automate ChatGPT to help you write your social posts and articles`, | ||||||||||||||||||||||||||||||||||||||||
| title: t('What is AI auto-complete?'), | ||||||||||||||||||||||||||||||||||||||||
| description: t(`We automate ChatGPT to help you write your social posts and articles`), | ||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -104,10 +106,11 @@ export const FAQSection: FC<{ title: string; description: string }> = ( | |||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| export const FAQComponent: FC = () => { | ||||||||||||||||||||||||||||||||||||||||
| const list = useFaqList(); | ||||||||||||||||||||||||||||||||||||||||
| const t = useTranslations('Billing') | ||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||
| <div> | ||||||||||||||||||||||||||||||||||||||||
| <h3 className="text-[24px] text-center mt-[81px] mb-[40px]"> | ||||||||||||||||||||||||||||||||||||||||
| Frequently Asked Questions | ||||||||||||||||||||||||||||||||||||||||
| {t('FrequentlyAskedQuestions')} | ||||||||||||||||||||||||||||||||||||||||
| </h3> | ||||||||||||||||||||||||||||||||||||||||
| <div className="gap-[24px] flex-col flex select-none"> | ||||||||||||||||||||||||||||||||||||||||
| {list.map((item, index) => ( | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add path attribute to cookie for enhanced security.
Consider adding the
pathattribute to the cookie configuration to restrict its scope to the minimum required path:response.cookie('NEXT_LOCALE', language, { domain: getCookieUrlFromDomain(process.env.FRONTEND_URL ?? ''), secure: true, httpOnly: true, maxAge: maxAge, expires: new Date(Date.now() + maxAge), sameSite: 'none', + path: '/', // Restrict cookie to root path or specific path as needed });📝 Committable suggestion