Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/add-i18next-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@youversion/platform-react-ui": minor
Comment thread
camrun91 marked this conversation as resolved.
---

Add i18next internationalization support with one extractable string ("Verse of The Day"). i18next and react-i18next are optional peer dependencies so existing consumers are unaffected. The SDK creates an isolated i18next instance (no global singleton mutation) and falls back to English by default.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ yarn-error.log*

# Claude Code
.claude/
.omc/

# Storybook
*storybook.log
Expand Down
12 changes: 11 additions & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,18 @@
"tw-animate-css": "1.4.0"
},
"peerDependencies": {
"i18next": ">=26.0.0",
"react": ">=19.1.0 <20.0.0",
"react-dom": ">=19.1.0 <20.0.0"
"react-dom": ">=19.1.0 <20.0.0",
"react-i18next": ">=17.0.0"
},
"peerDependenciesMeta": {
"i18next": {
"optional": true
},
"react-i18next": {
"optional": true
}
},
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
"devDependencies": {
"@internal/eslint-config": "workspace:*",
Expand Down
5 changes: 4 additions & 1 deletion packages/ui/src/components/verse-of-the-day.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
useVersion,
} from '@youversion/platform-react-hooks';
import React from 'react';
import { useTranslation } from 'react-i18next';
import i18n from '@/i18n';
Comment thread
greptile-apps[bot] marked this conversation as resolved.
import { AnimatedHeight } from '@/components/animated-height';
import { BibleAppLogoLockup } from '@/components/bible-app-logo-lockup';
import { LoaderIcon } from '@/components/icons/loader';
Expand Down Expand Up @@ -89,6 +91,7 @@ export function VerseOfTheDay({
showBibleAppAttribution = true,
size = 'default',
}: VerseOfTheDayProps): React.ReactElement {
const { t } = useTranslation(undefined, { i18n });
Comment thread
camrun91 marked this conversation as resolved.
const day = React.useMemo(() => dayOfYear || getDayOfYear(new Date()), [dayOfYear]);
const verseRef = React.useRef<HTMLDivElement>(null);
const { data, loading: loadingVerseOfTheDay, error: errorVerseOfTheDay } = useVerseOfTheDay(day);
Expand Down Expand Up @@ -147,7 +150,7 @@ export function VerseOfTheDay({
'trim-both yv:line-clamp-1 yv:text-muted-foreground yv:uppercase yv:text-xs yv:font-medium yv:select-none'
}
>
Verse of The Day
{t('verseOfTheDay')}
</p>
</div>
{showShareButton ? (
Expand Down
27 changes: 27 additions & 0 deletions packages/ui/src/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import i18next, { type i18n as I18nInstance } from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './locales/en.json';

const defaultNS = 'translation';

export const resources = {
en: { [defaultNS]: en },
} as const;

const i18n: I18nInstance = i18next.createInstance();

i18n
.use(initReactI18next)
Comment thread
cameronapak marked this conversation as resolved.
.init({
resources,
defaultNS,
fallbackLng: 'en',
interpolation: {
escapeValue: false, // React already escapes
},
})
.catch((err: unknown) => {
console.error('[youversion-sdk] i18n initialization failed:', err);
});

export default i18n;
3 changes: 3 additions & 0 deletions packages/ui/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"verseOfTheDay": "Verse of The Day"
}
87 changes: 74 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading