{"id":44360107,"url":"https://github.com/mathtechstudio/roblox-slang","last_synced_at":"2026-02-18T11:06:18.952Z","repository":{"id":336824292,"uuid":"1151230929","full_name":"mathtechstudio/roblox-slang","owner":"mathtechstudio","description":"A Type-safe internationalization (i18n) code generator for Roblox experiences","archived":false,"fork":false,"pushed_at":"2026-02-10T22:00:29.000Z","size":481,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-12T00:19:27.092Z","etag":null,"topics":["i18n","lua","luau","roblox","roblox-studio","sync"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mathtechstudio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["protheeuz"],"custom":["https://saweria.co/iqbalfauzien","https://www.paypal.com/paypalme/iqbalfauzien"]}},"created_at":"2026-02-06T07:56:53.000Z","updated_at":"2026-02-10T22:00:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mathtechstudio/roblox-slang","commit_stats":null,"previous_names":["protheeuz/roblox-slang","mathtechstudio/roblox-slang"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mathtechstudio/roblox-slang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathtechstudio%2Froblox-slang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathtechstudio%2Froblox-slang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathtechstudio%2Froblox-slang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathtechstudio%2Froblox-slang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mathtechstudio","download_url":"https://codeload.github.com/mathtechstudio/roblox-slang/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathtechstudio%2Froblox-slang/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29375581,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T08:51:36.827Z","status":"ssl_error","status_checked_at":"2026-02-12T08:51:26.849Z","response_time":55,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["i18n","lua","luau","roblox","roblox-studio","sync"],"created_at":"2026-02-11T17:18:49.718Z","updated_at":"2026-02-18T11:06:18.946Z","avatar_url":"https://github.com/mathtechstudio.png","language":"Rust","funding_links":["https://github.com/sponsors/protheeuz","https://saweria.co/iqbalfauzien","https://www.paypal.com/paypalme/iqbalfauzien"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"docs/assets/featured-image.png\" alt=\"Roblox Slang\" height=\"300\" /\u003e\n\u003c/div\u003e\n\n\u003cdiv\u003e\u0026nbsp;\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![Version](https://img.shields.io/github/v/release/mathtechstudio/roblox-slang?style=for-the-badge\u0026logo=github)](https://github.com/mathtechstudio/roblox-slang/releases)\n[![Roblox](https://img.shields.io/badge/Platform-Roblox-00A2FF?style=for-the-badge\u0026logo=roblox\u0026logoColor=white)](https://www.roblox.com)\n[![Rust](https://img.shields.io/badge/Built_with-Rust-orange?style=for-the-badge\u0026logo=rust\u0026logoColor=white)](https://www.rust-lang.org)\n[![Generates](https://img.shields.io/badge/Generates-Luau-00A2FF?style=for-the-badge\u0026logo=lua\u0026logoColor=white)](https://luau-lang.org)\n[![License](https://img.shields.io/badge/License-MIT-blue?style=for-the-badge)](LICENSE)\n[![Tests](https://img.shields.io/badge/Tests-681_passing-success?style=for-the-badge)](tests/)\n\n\u003c/div\u003e\n\n\u003chr /\u003e\n\n**Roblox Slang** is a Type-safe internationalization (i18n) code generator for Roblox experiences. Write translations in JSON/YAML, generate type-safe Luau code with autocomplete support.\n\n## Why Roblox Slang?\n\nRoblox's native localization system uses string literals for translation keys, leading to runtime errors from typos and no IDE support. Roblox Slang solves this by generating type-safe Luau code at build time.\n\n**Before (Roblox native):**\n\n```lua\nlocal translator = LocalizationService:GetTranslatorForPlayerAsync(player)\nlocal text = translator:FormatByKey(\"UI_Buttons_Confirm\") -- Typo-prone, no autocomplete\n\n-- Typo = runtime error\nlocal text = translator:FormatByKey(\"UI_Buttns_Confirm\") -- ERROR at runtime!\n```\n\n**After (Roblox Slang):**\n\n```lua\nlocal t = Translations.new(\"en\")\nlocal text = t.ui.buttons.confirm() -- Autocomplete works, type-safe\n\n-- Typo = build-time error\nlocal text = t.ui.buttns.confirm() -- ERROR: Property doesn't exist (caught at build time)\n```\n\n## Features\n\n- **Type-safe translation access** - Autocomplete and type checking in your IDE\n- **Three localization modes** - Embedded (default), Cloud, or Hybrid for flexibility\n- **String interpolation** - `{name}`, `{count:int}` with parameter validation\n- **Pluralization** - CLDR rules (zero/one/two/few/many/other)\n- **Nested namespaces** - Clean syntax: `t.ui.buttons.buy()`\n- **Watch mode** - Auto-rebuild on file changes\n- **CSV generation** - Export to Roblox Cloud Localization format\n- **Cloud sync** - Bidirectional sync with Roblox Cloud Localization Tables\n- **Zero runtime dependencies** - Generated code is pure Luau\n- **Multiple input formats** - JSON, YAML, or CSV\n- **Translation overrides** - A/B testing and seasonal events support\n\n## Installation\n\nRoblox Slang is a CLI tool that generates code. Choose your preferred installation method:\n\n### Via Rokit (Recommended)\n\n[Rokit](https://github.com/rojo-rbx/rokit) is the fastest and most modern toolchain manager for Roblox projects.\n\n```bash\n# Add to your project\nrokit add mathtechstudio/roblox-slang\n\n# Or install globally\nrokit add --global mathtechstudio/roblox-slang\n```\n\n**rokit.toml:**\n\n```toml\n[tools]\nroblox-slang = \"mathtechstudio/roblox-slang@2.0.1\"\n```\n\n### Via Aftman\n\n\u003e **Note:** Aftman is no longer actively maintained. We recommend using [Rokit](#via-rokit-recommended) or [Foreman](#via-foreman) for new projects.\n\n[Aftman](https://github.com/LPGhatguy/aftman) provides exact version dependencies and a trust-based security model.\n\n```bash\n# Add to your project\naftman add mathtechstudio/roblox-slang\n\n# Or install globally\naftman add --global mathtechstudio/roblox-slang\n```\n\n**aftman.toml:**\n\n```toml\n[tools]\nroblox-slang = \"mathtechstudio/roblox-slang@2.0.1\"\n```\n\n### Via Foreman\n\n[Foreman](https://github.com/Roblox/foreman) is the original Roblox toolchain manager, battle-tested in production.\n\n**foreman.toml:**\n\n```toml\n[tools]\nroblox-slang = { github = \"mathtechstudio/roblox-slang\", version = \"2.0.1\" }\n```\n\n```bash\nforeman install\n```\n\n### From GitHub Releases (Manual)\n\nDownload pre-built binaries for your platform:\n\n- `roblox-slang-2.0.1-linux-x86_64.zip`\n- `roblox-slang-2.0.1-linux-aarch64.zip`\n- `roblox-slang-2.0.1-windows-x86_64.zip`\n- `roblox-slang-2.0.1-windows-aarch64.zip`\n- `roblox-slang-2.0.1-macos-x86_64.zip`\n- `roblox-slang-2.0.1-macos-aarch64.zip`\n\nExtract and add to your PATH, or use a tool manager for automatic updates.\n\n### From Source (Cargo)\n\n```bash\n# Install from crates.io\ncargo install roblox-slang\n\n# Or build from source\ngit clone https://github.com/mathtechstudio/roblox-slang.git\ncd roblox-slang\ncargo install --locked --path .\n```\n\n### Verify Installation\n\n```bash\nroblox-slang --version\n# Output: roblox-slang 2.0.1\n```\n\n## Quick Start\n\n### 1. Initialize Project\n\n```bash\nroblox-slang init\n```\n\nCreates:\n\n- `slang-roblox.yaml` - Configuration file\n- `translations/` - Translation files directory\n\n### 2. Create Translations\n\n`translations/en.json`:\n\n```json\n{\n  \"ui\": {\n    \"buttons\": {\n      \"buy\": \"Buy\",\n      \"sell\": \"Sell\"\n    },\n    \"messages\": {\n      \"greeting\": \"Hello, {name}!\",\n      \"items\": {\n        \"zero\": \"No items\",\n        \"one\": \"1 item\",\n        \"other\": \"{count} items\"\n      }\n    }\n  }\n}\n```\n\n`translations/es.json`:\n\n```json\n{\n  \"ui\": {\n    \"buttons\": {\n      \"buy\": \"Comprar\",\n      \"sell\": \"Vender\"\n    },\n    \"messages\": {\n      \"greeting\": \"¡Hola, {name}!\",\n      \"items\": {\n        \"zero\": \"Sin artículos\",\n        \"one\": \"1 artículo\",\n        \"other\": \"{count} artículos\"\n      }\n    }\n  }\n}\n```\n\n### 3. Build\n\n```bash\n# One-time build\nroblox-slang build\n\n# Watch mode (auto-rebuild on changes)\nroblox-slang build --watch\n```\n\nGenerates:\n\n- `output/Translations.lua` - Main module\n- `output/types/Translations.d.luau` - Type definitions for LSP\n- `output/roblox_upload.csv` - Roblox Cloud format\n\n### 4. Add to Your Game\n\n#### Option A: Manual (Roblox Studio)\n\n1. Copy `output/Translations.lua` to `ReplicatedStorage` in Roblox Studio\n2. Rename to `Translations` (ModuleScript)\n3. Optionally copy `output/types/Translations.d.luau` for LSP autocomplete\n\n#### Option B: Rojo (Automatic Sync)\n\nSet output directory to match your Rojo project structure:\n\n**slang-roblox.yaml:**\n\n```yaml\noutput_directory: src/ReplicatedStorage/Translations\n```\n\n**default.project.json:**\n\n```json\n{\n  \"name\": \"MyGame\",\n  \"tree\": {\n    \"$className\": \"DataModel\",\n    \"ReplicatedStorage\": {\n      \"$className\": \"ReplicatedStorage\",\n      \"$path\": \"src/ReplicatedStorage\"\n    }\n  }\n}\n```\n\nRun `roblox-slang build` and Rojo will automatically sync to Studio!\n\n### 5. Use in Game\n\n```lua\nlocal Translations = require(ReplicatedStorage.Translations)\n\n-- Create instance for locale\nlocal t = Translations.new(\"en\")\n\n-- Simple translations\nprint(t.ui.buttons.buy())  -- \"Buy\"\n\n-- With parameters\nprint(t.ui.messages.greeting({ name = \"Player123\" }))  -- \"Hello, Player123!\"\n\n-- Pluralization\nprint(t.ui.messages.items(0))  -- \"No items\"\nprint(t.ui.messages.items(1))  -- \"1 item\"\nprint(t.ui.messages.items(5))  -- \"5 items\"\n\n-- Switch locale at runtime\nt:setLocale(\"es\")\nprint(t.ui.buttons.buy())  -- \"Comprar\"\n\n-- Auto-detect player locale\nlocal function onPlayerAdded(player)\n    local t = Translations.newForPlayer(player)\n    print(t.ui.messages.greeting({ name = player.DisplayName }))\nend\n```\n\n## Configuration\n\n`slang-roblox.yaml`:\n\n```yaml\n# Base locale (fallback when translation missing)\nbase_locale: en\n\n# Supported locales\nsupported_locales:\n  - en\n  - es\n  - id\n\n# Input directory for translation files\ninput_directory: translations\n\n# Output directory for generated code\n# For Rojo users: Set to your Rojo-tracked folder (e.g., src/ReplicatedStorage/Translations)\n# For manual users: Keep as \"output\" and copy to Studio manually\noutput_directory: output\n\n# Optional: Namespace for generated module (null = no namespace)\nnamespace: null\n\n# Localization mode (NEW in v2.0.1)\n# Controls how translations are loaded at runtime\nlocalization:\n  # Mode: embedded (default) - Translations embedded in generated code, no cloud dependency\n  # Other options:\n  #   - cloud: Use Roblox Cloud LocalizationService only (requires cloud upload)\n  #   - hybrid: Try cloud first, fallback to embedded (best of both worlds)\n  mode: embedded\n\n# Optional: Translation overrides (for A/B testing, seasonal events)\noverrides:\n  enabled: true\n  file: overrides.yaml\n\n# Optional: Analytics tracking\nanalytics:\n  enabled: true\n  track_missing: true\n  track_usage: true\n```\n\n## Main Features\n\n### Localization Modes\n\n**NEW in v2.0.1:** Choose how translations are loaded at runtime.\n\n#### Embedded Mode (Default)\n\nTranslations are embedded directly in the generated Luau code. No cloud dependency required.\n\n```yaml\nlocalization:\n  mode: embedded\n```\n\n**Benefits:**\n\n- Works offline (no LocalizationService dependency)\n- Fastest performance (direct table lookup)\n- No cloud setup required\n- Perfect for single-player or offline games\n\n**Usage:**\n\n```lua\nlocal t = Translations.new(\"en\")\nprint(t.ui.buttons.buy())  -- Direct lookup from embedded data\n```\n\n#### Cloud Mode\n\nUses Roblox Cloud LocalizationService exclusively. Requires uploading translations to Roblox Cloud.\n\n```yaml\nlocalization:\n  mode: cloud\n```\n\n**Benefits:**\n\n- Automatic Text Capture (ATC) integration\n- Automatic translation via Roblox AI\n- Translator Portal collaboration\n- Analytics via Roblox Dashboard\n\n**Usage:**\n\n```lua\nlocal t = Translations.new(\"en\")\nprint(t.ui.buttons.buy())  -- Fetches from LocalizationService\n```\n\n**Requirements:**\n\n- Must run `roblox-slang upload` to sync translations to cloud\n- Requires cloud configuration in `slang-roblox.yaml`\n\n#### Hybrid Mode\n\nBest of both worlds: tries cloud first, falls back to embedded on error.\n\n```yaml\nlocalization:\n  mode: hybrid\n```\n\n**Benefits:**\n\n- Cloud features when available (ATC, auto-translation)\n- Embedded fallback for reliability\n- Graceful degradation on cloud errors\n- Works in Studio and production\n\n**Usage:**\n\n```lua\nlocal t = Translations.new(\"en\")\nprint(t.ui.buttons.buy())  -- Tries cloud, falls back to embedded\n```\n\n**Use Cases:**\n\n- Games transitioning from embedded to cloud\n- Games that need offline support with cloud benefits\n- Development (Studio) vs production (cloud) workflows\n\n### String Interpolation\n\n```json\n{\n  \"welcome\": \"Welcome, {name}!\",\n  \"score\": \"Score: {points:int}\",\n  \"price\": \"Price: ${amount:fixed}\"\n}\n```\n\n```lua\nprint(t.welcome({ name = \"Player\" }))  -- \"Welcome, Player!\"\nprint(t.score({ points = 1234 }))      -- \"Score: 1234\"\nprint(t.price({ amount = 99.99 }))     -- \"Price: $99.99\"\n```\n\n### Pluralization (CLDR Rules)\n\n```json\n{\n  \"items\": {\n    \"zero\": \"No items\",\n    \"one\": \"1 item\",\n    \"other\": \"{count} items\"\n  }\n}\n```\n\n```lua\nprint(t.items(0))  -- \"No items\"\nprint(t.items(1))  -- \"1 item\"\nprint(t.items(5))  -- \"5 items\"\n```\n\n### Locale Switching\n\n```lua\nlocal t = Translations.new(\"en\")\nprint(t.ui.buttons.buy())  -- \"Buy\"\n\nt:setLocale(\"es\")\nprint(t.ui.buttons.buy())  -- \"Comprar\"\n```\n\n### Auto-Detect Player Locale\n\n```lua\n-- Automatically uses player's country/locale\nlocal t = Translations.newForPlayer(player)\n```\n\n### Translation Overrides\n\nFor A/B testing or seasonal events:\n\n`overrides.yaml`:\n\n```yaml\nen:\n  ui.buttons.buy: \"Purchase Now!\"  # Override for A/B test\n  \nes:\n  ui.buttons.buy: \"¡Comprar Ahora!\"\n```\n\nPriority: `overrides.yaml` \u003e `translations/*.json`\n\n## Documentation\n\n📚 **[Complete Documentation](docs/index.md)**\n\nQuick links:\n\n- **[Getting Started](docs/getting-started.md)** - Installation and first project\n- **[Configuration](docs/guides/configuration.md)** - Config file reference\n- **[String Interpolation](docs/guides/string-interpolation.md)** - Parameter usage\n- **[Pluralization](docs/guides/pluralization.md)** - CLDR plural rules\n- **[Roblox Cloud Integration](docs/guides/roblox-cloud.md)** - Upload to Roblox Cloud\n- **[Rojo Integration](docs/integration/rojo.md)** - Use with Rojo for automatic syncing\n- **[CLI Reference](docs/reference/cli-reference.md)** - Complete command reference\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `roblox-slang init` | Initialize new project |\n| `roblox-slang init --with-overrides` | Initialize with overrides template |\n| `roblox-slang build` | Build translations once |\n| `roblox-slang build --watch` | Watch mode (auto-rebuild) |\n| `roblox-slang upload` | Upload translations to Roblox Cloud |\n| `roblox-slang download` | Download translations from Roblox Cloud |\n| `roblox-slang sync` | Bidirectional sync with merge strategies |\n| `roblox-slang import \u003cCSV_FILE\u003e` | Import from Roblox CSV file |\n| `roblox-slang validate --all` | Check for missing/unused keys and conflicts |\n| `roblox-slang migrate --from \u003cformat\u003e` | Migrate from other formats |\n\nSee [CLI Reference](docs/reference/cli-reference.md) for complete command documentation.\n\n## Roblox Cloud Integration\n\nRoblox Slang provides seamless integration with Roblox Cloud Localization Tables through bidirectional sync commands.\n\n### Quick Start\n\n1. **Get your API key** from [Creator Dashboard](https://create.roblox.com/dashboard/creations), go to the [API Keys](https://create.roblox.com/dashboard/credentials) page.\n\n2. **Set environment variable**:\n\n   ```bash\n   export ROBLOX_CLOUD_API_KEY=your_api_key_here\n   ```\n\n3. **Upload translations**:\n\n   ```bash\n   roblox-slang upload --table-id YOUR_TABLE_ID\n   ```\n\n4. **Download translations**:\n\n   ```bash\n   roblox-slang download --table-id YOUR_TABLE_ID\n   ```\n\n5. **Bidirectional sync**:\n\n   ```bash\n   roblox-slang sync --table-id YOUR_TABLE_ID --strategy merge\n   ```\n\n### Cloud Sync Commands\n\n| Command | Description |\n|---------|-------------|\n| `roblox-slang upload` | Upload local translations to Roblox Cloud |\n| `roblox-slang download` | Download translations from Roblox Cloud |\n| `roblox-slang sync` | Bidirectional sync with merge strategies |\n\n### Merge Strategies\n\n- **overwrite** - Upload all local translations (cloud is overwritten)\n- **merge** - Upload local-only, download cloud-only, prefer cloud for conflicts\n- **skip-conflicts** - Upload local-only, download cloud-only, skip conflicts\n\n### Configuration\n\nAdd cloud settings to `slang-roblox.yaml`:\n\n```yaml\ncloud:\n  table_id: YOUR_TABLE_ID\n  game_id: YOUR_GAME_ID\n  api_key: ${ROBLOX_CLOUD_API_KEY}  # Or set directly (not recommended)\n  strategy: merge\n```\n\n### Benefits of Cloud Sync\n\n- **Automatic Text Capture (ATC)** - Roblox captures UI strings automatically\n- **Automatic translation** - Roblox AI translates to supported languages\n- **Translator Portal** - Collaborate with translators via Roblox\n- **Analytics** - Track translation coverage via Roblox Dashboard\n- **Multi-game synchronization** - Share translations across games\n- **Version control** - Keep local and cloud in sync\n\nSee [Roblox Cloud Integration Guide](docs/guides/roblox-cloud.md) for complete documentation.\n\n## Examples\n\nSee [`tests/basic/`](tests/basic/) for a complete example with 173 translation keys across 3 locales.\n\n## Development\n\nFor contributors:\n\n```bash\n# Clone repository\ngit clone https://github.com/mathtechstudio/roblox-slang.git\ncd roblox-slang\n\n# Install Rust (1.88+)\nrustup override set 1.88.0\n\n# Build\ncargo build\n\n# Run tests (103 tests)\ncargo test\n\n# Run CLI\ncargo run -- --help\n```\n\n## Contributing\n\nContributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n## License\n\nMIT License - see [LICENSE](LICENSE)\n\n## References\n\n- [Roblox Localization Documentation](https://create.roblox.com/docs/production/localization)\n- [Unicode CLDR Plural Rules](https://cldr.unicode.org/)\n- [Luau Language Reference](https://luau-lang.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathtechstudio%2Froblox-slang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathtechstudio%2Froblox-slang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathtechstudio%2Froblox-slang/lists"}