@studyjoyful/shared

v1.0.12

Published

Shared code for StudyJoyful Web and App (i18n, constants, types, utils)

Downloads

74

Readme

@studyjoyful/shared

Shared code for StudyJoyful Web and App.

šŸŽÆ Design Principles

i18n: Single Source of Truth

āš ļø Critical: This package is the ONLY source of translations. Web and App do NOT have their own locales/ directories.

| Principle | Description | | ----------------- | --------------------------------------- | | Single Source | All translations here, nowhere else | | English Only | Singapore market = English only | | Modular | Split by feature (auth, chat, tasks...) | | Shared | Web + App import from this package |

šŸ“¦ Modules

| Module | Description | Exports | | ------------- | -------------------- | ----------------------------------------- | | i18n | Internationalization | resources, namespaces, defaultNS | | constants | Shared constants | EXAMPLES_BY_GRADE, getExamplesByGrade | | types | Type definitions | ChildGrade, Subject, Example | | utils | Utility functions | randomSelect, shuffle |

šŸš€ Usage

Installation (yarn link)

# In this package
cd studyjoyful-shared
yarn link

# In Web
cd ../studyjoyful-web
yarn link "@studyjoyful/shared"

# In App
cd ../studyjoyful-app
yarn link "@studyjoyful/shared"

App Metro Config

The App requires special Metro configuration:

// metro.config.js
const sharedPackagePath = path.resolve(__dirname, "../studyjoyful-shared");

config.watchFolders = [sharedPackagePath];
config.resolver.nodeModulesPaths = [
  path.resolve(__dirname, "node_modules"),
  path.resolve(sharedPackagePath, "node_modules"),
];

const ALIASES = {
  "@studyjoyful/shared": sharedPackagePath + "/src",
};

Import Examples

// i18n
import { resources, namespaces, defaultNS } from "@studyjoyful/shared";

// Constants
import { EXAMPLES_BY_GRADE, getExamplesByGrade } from "@studyjoyful/shared";

// Types
import type { ChildGrade, Subject, Example } from "@studyjoyful/shared";

// Utils
import { randomSelect, shuffle } from "@studyjoyful/shared";

šŸ“ Structure

src/
ā”œā”€ā”€ index.ts           # Main exports
ā”œā”€ā”€ i18n/
│   ā”œā”€ā”€ index.ts
│   └── locales/
│       └── en/        # English translations
│           ā”œā”€ā”€ common.json
│           ā”œā”€ā”€ auth.json
│           ā”œā”€ā”€ chat.json
│           ā”œā”€ā”€ tasks.json
│           ā”œā”€ā”€ learning.json
│           ā”œā”€ā”€ profile.json
│           ā”œā”€ā”€ errors.json
│           └── sidebar.json
ā”œā”€ā”€ constants/
│   ā”œā”€ā”€ index.ts
│   └── examples.ts    # Learning examples
ā”œā”€ā”€ types/
│   ā”œā”€ā”€ index.ts
│   ā”œā”€ā”€ child.ts       # ChildGrade, Subject
│   └── common.ts      # PaginationParams
└── utils/
    ā”œā”€ā”€ index.ts
    └── random.ts      # randomSelect, shuffle

šŸ”§ Development

# Type check
npx tsc --noEmit

# After changes, test in both:
# 1. Web (hot reload)
# 2. App (metro refresh)

šŸ“ Adding New Content

  1. Create file in appropriate module
  2. Export from module's index.ts
  3. Re-export from main src/index.ts
  4. Test in both Web and App

šŸŒ Adding Translations

DO:

# Add to this package
src/i18n/locales/en/auth.json    # āœ… Correct

DON'T:

# Never create locales in consumer projects
studyjoyful-app/locales/         # āŒ WRONG
studyjoyful-web/locales/         # āŒ WRONG

Translation File Structure

// src/i18n/locales/en/auth.json
{
  "welcome": {
    "title": "StudyJoyful",
    "subtitle": "Turn homework into 10-minute learning games",
    "getStarted": "Get Started"
  },
  "errors": {
    "signInFailed": "Sign In Failed",
    "tryAgain": "Please try again"
  }
}

Usage in Consumer Projects

// lib/i18n.ts (in Web or App)
import { resources, namespaces, defaultNS } from "@studyjoyful/shared";

// Component
import { useTranslation } from "react-i18next";

function WelcomeScreen() {
  const { t } = useTranslation("auth");
  return <Text>{t("welcome.title")}</Text>;
}

Package: @studyjoyful/shared
Version: 1.0.0
Consumers: studyjoyful-web, studyjoyful-app
Language: English only (Singapore market)