Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions .changeset/add-i18next-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@youversion/platform-core": minor
"@youversion/platform-react-ui": minor
Comment thread
camrun91 marked this conversation as resolved.
"@youversion/platform-react-hooks": minor
---

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
2 changes: 2 additions & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"tailwind-merge": "3.3.1",
"i18next": "^26.0.0",
"react-i18next": "^17.0.0",
"tw-animate-css": "1.4.0"
},
"peerDependencies": {
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