Full Code of Quilljou/transmart for AI

main 012411f14183 cached
73 files
349.2 KB
105.6k tokens
38 symbols
1 requests
Download .txt
Showing preview only (406K chars total). Download the full file or copy to clipboard to get everything.
Repository: Quilljou/transmart
Branch: main
Commit: 012411f14183
Files: 73
Total size: 349.2 KB

Directory structure:
gitextract_t6167sma/

├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.md
│       ├── custom.md
│       └── feature_request.md
├── .gitignore
├── .prettierrc.js
├── CONTRIBUTING.md
├── LICENSE
├── README-zh_CN.md
├── README.md
├── commitlint.config.js
├── examples/
│   ├── README.md
│   ├── chrome-extension/
│   │   ├── README.md
│   │   ├── _locales/
│   │   │   └── en/
│   │   │       └── messages.json
│   │   ├── feed.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── transmart.config.js
│   └── next.js/
│       ├── @types/
│       │   └── i18next.d.ts
│       ├── components/
│       │   ├── Footer.tsx
│       │   └── Header.tsx
│       ├── next-env.d.ts
│       ├── next-i18next.config.js
│       ├── next-utils.config.js
│       ├── next.config.js
│       ├── package.json
│       ├── pages/
│       │   ├── _app.tsx
│       │   ├── _document.tsx
│       │   ├── index.tsx
│       │   └── second-page.tsx
│       ├── public/
│       │   ├── app.css
│       │   └── locales/
│       │       └── en/
│       │           ├── common.json
│       │           ├── footer.json
│       │           └── second-page.json
│       ├── transmart.config.js
│       ├── tsconfig.json
│       └── vercel.json
├── lerna.json
├── package.json
├── packages/
│   ├── cli/
│   │   ├── README.md
│   │   ├── bin/
│   │   │   └── transmart.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── cli.ts
│   │   │   ├── index.ts
│   │   │   ├── options.ts
│   │   │   └── types.ts
│   │   └── tsconfig.build.json
│   └── core/
│       ├── README.md
│       ├── package.json
│       ├── src/
│       │   ├── index.ts
│       │   ├── language.ts
│       │   ├── limit.ts
│       │   ├── split.ts
│       │   ├── task.ts
│       │   ├── translate.ts
│       │   ├── transmart.ts
│       │   ├── types.ts
│       │   └── util.ts
│       ├── test/
│       │   └── locales/
│       │       ├── de/
│       │       │   ├── common.json
│       │       │   └── tos.json
│       │       ├── en/
│       │       │   ├── common.json
│       │       │   ├── large-file.json
│       │       │   └── tos.json
│       │       ├── jp/
│       │       │   └── common.json
│       │       ├── zh-CN/
│       │       │   ├── common.json
│       │       │   ├── large-file.json
│       │       │   └── tos.json
│       │       └── zh-TW/
│       │           ├── common.json
│       │           └── tos.json
│       └── tsconfig.build.json
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

# Use 4 spaces for the Python and HTML files
[*.py, *.html]
indent_size = 4

# The JSON files contain newlines inconsistently
[*.json]
insert_final_newline = ignore

# Minified JavaScript files shouldn't be changed
[**.min.js]
indent_style = ignore
insert_final_newline = ignore

# Makefiles always use tabs for indentation
[Makefile]
indent_style = tab

# Batch files use tabs for indentation
[*.bat]
indent_style = tab

[*.md]
trim_trailing_whitespace = false


================================================
FILE: .eslintignore
================================================
examples


================================================
FILE: .eslintrc
================================================
{
  "root": true,
  "parser": "@typescript-eslint/parser",
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "ignorePatterns": ["lib"],
  "plugins": [
    "@typescript-eslint",
    "prettier"
  ],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier"
  ]
}


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**Smartphone (please complete the following information):**
 - Device: [e.g. iPhone6]
 - OS: [e.g. iOS8.1]
 - Browser [e.g. stock browser, safari]
 - Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/custom.md
================================================
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''

---




================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .gitignore
================================================
# Created by https://www.toptal.com/developers/gitignore/api/node,macOS
# Edit at https://www.toptal.com/developers/gitignore?templates=node,macOS

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### macOS Patch ###
# iCloud generated files
*.icloud

### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

### Node Patch ###
# Serverless Webpack directories
.webpack/

# Optional stylelint cache

# SvelteKit build / generate output
.svelte-kit

# End of https://www.toptal.com/developers/gitignore/api/node,macOS
n

lib
package-lock.json
# for testing
packages/core/transmart.config.js
examples/**/locales/*
!examples/**/locales/en

examples/**/_locales/*
!examples/**/_locales/en


================================================
FILE: .prettierrc.js
================================================
module.exports = {
  printWidth: 120,
  tabWidth: 2,
  useTabs: false,
  semi: false,
  singleQuote: true,
  quoteProps: 'as-needed',
  trailingComma: 'all',
  bracketSpacing: true,
  arrowParens: 'always',
  requirePragma: false,
  insertPragma: false,
  proseWrap: 'preserve',
  htmlWhitespaceSensitivity: 'ignore',
  endOfLine: 'auto',
  embeddedLanguageFormatting: 'auto',
  singleAttributePerLine: false
}


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Transmart

1. Fork this repo

2. Clone your forked repo

3. Run it

```
npm install
npm run build:watch
```

4. Make changes, pass linters, push to your repo

5. Create a pull request 



================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2023 Quill Zhou

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README-zh_CN.md
================================================
<p align="center">
  <img src="./assets/logo.png" />
</p>

<p align="center">
<b> Transmart - 利用 AI 自动化您的 i18n</b>
</p>

简体中文 | [English](./README.md)


![alt](./assets/record.gif)

![npm](https://img.shields.io/npm/v/@transmart/cli?style=flat-square)
[![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?logo=codesandbox)](https://codesandbox.io/p/sandbox/v12-12v2h6?file=%2FREADME.md)

Transmart 是一个开源的开发者工具,利用 ChatGPT 实现 i18n 翻译自动化。给定一个基础语言并指定需要输出的所有语言,运行它将生成所有 i18n 区域设置文件。

它由两部分组成:Cli 和 Core。Core 是 Transmart 的 NodeJS 核心实现,而 Cli 是封装了 Core 的命令行工具。在大多数情况下,只使用 Cli 就足够了。

该项目目前正在积极开发中,欢迎 PR,也可以在[Twitter](https://twitter.com/quillzhou)上联系我

## 特征

- [x] 支持大型文件,不必担心 4096 个标记限制
- [x] 支持使用[Intl.DisplayNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/DisplayNames)显示的所有语言,以及可以通过 ChatGPT 处理的所有语言。
- [x] 支持覆盖 AI 翻译值
- [x] 支持[i18next](https://www.i18next.com/)
- [ ] 支持[vue-i18n](https://kazupon.github.io/vue-i18n/)
- [x] 支持[Chrome.i18n](https://developer.chrome.com/docs/webstore/i18n/#choosing-locales-to-support)
- [x] 支持 Glob 名称空间匹配
- [x] 支持自定义 OpenAI 模型、API 端点
- [ ] 支持自定义区域设置文件结构
- [ ] 支持 iOS
- [ ] 支持 Android

## 设置

> Transmart 要求 Node 版本 13 或更高。

### 1. 安装

要安装 Transmart,请运行:

````sh
npm install @transmart/cli -D

# or

yarn add @transmart/cli


### 2. 项目配置
首先,在项目根目录中创建一个transmart.config.js文件,或任何其他文件格式 `cosmiconfig` 可以搜索到的

transmart.config.js

```js
module.exports = {
  baseLocale: 'en',
  locales: ['fr', 'jp', 'de'],
  localePath: 'public/locales',
  openAIApiKey: 'your-own-openai-api-key',
  overrides: {
    'zh-CN': {
      common: {
        create_app: 'Create my Application',
      },
    },
  },
}
````

所有选项可 [参考](#选项)

### 3. 翻译。

向您的 npm 脚本添加 transmart 命 令

```json
{
  "translate": "transmart"
}
```

然后执行

```sh
npm run translate

```

或者您可以在命令行中直接使用 npx 前缀执行

```sh
npx transmart
```

如果对 AI 翻译的结果不满意,请使用 [overrides](#选项) 选项部分覆盖生成的 JSON

享受 i18n 吧 🎉🎉

## 选项

| 名称             | 类型                                                  | 描述                                                                           | 是否必须 |
| ---------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------ | :------: |
| baseLocale       | string                                                | Transmart 将用作翻译参考的语言。                                               |    是    |
| locales          | string[]                                              | 所有需要翻译的语言                                                             |    是    |
| localePath       | string                                                | 存储国际化文件的位置                                                           |    是    |
| openAIApiKey     | string                                                | OpenAI API 密钥                                                                |    是    |
| context     | string                                | 提供一些上下文让翻译更准确                                                                             |   否    |
| openAIApiModel   | string                                                | OpenAI API 模型,默认为“gpt-3.5-turbo-16k-0613”                                         |    否    |
| overrides        | `Record<string, Record<string, Record<string, any>>>` | 如果你不满意 AI 翻译结果,用于部分覆盖生成的 JSON (locale-namespace-key:value) |    否    |
| namespaceGlob    | string\|string[]                                      | 命名空间匹配项                                                                 |    否    |
| openAIApiUrl     | string                                                | 可选基本 OpenAI API url 地址,在使用代理时很有用                               |    否    |
| openAIApiUrlPath | string                                                | 可选的 OpenAI API url 地址, 在使用代理时很有用                                |    否    |
|                  |

## 贡献

要贡献到 Transmart,请参阅[contributing.md](./CONTRIBUTING.md)

## 受以下启发

- https://chatgpt-i18n.vercel.app/
- https://twitter.com/forgebitz/status/1634100746617597955
- https://github.com/yetone/openai-translator


================================================
FILE: README.md
================================================
<p align="center">
  <img src="./assets/logo.png" />
</p>

<p align="center">
  <b>Transmart - Automate your i18n localization with AI.</b>
</p>

English | [简体中文](./README-zh_CN.md)


![alt](./assets/record.gif)

![npm](https://img.shields.io/npm/v/@transmart/cli?style=flat-square)
[![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?logo=codesandbox)](https://codesandbox.io/p/sandbox/v12-12v2h6?file=%2FREADME.md)


Transmart is an open-source developer tool that utilizes ChatGPT to automate i18n translation. Given a base language and specifying all the languages that need to be output, running it will generate all i18n locale files.

It consists of two parts: Cli and Core. Core is the NodeJS core implementation of Transmart, while Cli is a command-line tool that encapsulates Core. In most cases, only Cli is used.

This project is currently under active development,PRs are welcome,reach me at [Twitter](https://twitter.com/quillzhou)

## Features

- [x] Supports large size files,don't worry about the 4096 tokens limit
- [x] Supports all languages that can be displayed using [Intl.DisplayNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/DisplayNames) and can be processed by ChatGPT.
- [x] Supports override AI translated values
- [x] Supports [i18next](https://www.i18next.com/)
- [ ] Supports [vue-i18n](https://kazupon.github.io/vue-i18n/)
- [x] Supports [Chrome.i18n](https://developer.chrome.com/docs/webstore/i18n/#choosing-locales-to-support)
- [x] Supports Glob namespace matching
- [x] Supports customizing OpenAI Model、API endpoint
- [ ] Supports custom locale file structure
- [ ] Supports iOS
- [ ] Supports Android

## Setup

> Transmart requires Node version 13 or higher.

### 1. Installation

To install Transmart, run:

```sh
npm install @transmart/cli -D

# or

yarn add @transmart/cli
```

### 2. Project setup

First, create a transmart.config.js file in the root of your project. or any others file format [cosmiconfig](https://www.npmjs.com/package/cosmiconfig?activeTab=readme) can search for

`transmart.config.js`

```js
module.exports = {
  baseLocale: 'en',
  locales: ['fr', 'jp', 'de'],
  localePath: 'public/locales',
  openAIApiKey: 'your-own-openai-api-key',
  overrides: {
    'zh-CN': {
      common: {
        create_app: 'Create my Application',
      },
    },
  },
}
```




All Options [Reference](#options)

### 3. Translate.

Add transmart command to your npm scripts

```sh
{
  "translate": "transmart"
}
```

And then execute

```sh
npm run translate
```

Or you can execute directly with `npx` prefix in command line

```
npx transmart
```

If you are not satisfied with the result of AI translation,use [`overrides`](#options) option to overwrite the generated JSON partially

🎉🎉 Enjoy i18n



## Examples

- [next.js](./examples/next.js)
- [chrome extension](./examples/chrome-extension/)

## Options

| Name                    | Type                                                 | Description                                                                                                                                                                                                                                                                                    | Required |
|-------------------------|------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| :------: |
| baseLocale              | string                                               | The language that Transmart will use as translation ref.                                                                                                                                                                                                                                       |   Yes    |
| locales                 | string[]                                             | All languages that need to be translated                                                                                                                                                                                                                                                       |   Yes    |
| localePath              | string                                               | Where you store your locale files                                                                                                                                                                                                                                                              |   Yes    |
| openAIApiKey            | string                                               | The OpenAI API Key.                                                                                                                                                                                                                                                                            |   Yes    |
| context                 | string                                               | Provide some context for a more accurate translation.                                                                                                                                                                                                                                          |   No    |
| openAIApiModel          | string                                               | OpenAI API model, default to `gpt-3.5-turbo-16k-0613`                                                                                                                                                                                                                                          |    No    |
| overrides               | `Record<string, Record<string, Record<string, any>>>` | used to overwrite the generated JSON if you are not satisfied with the result of AI translation (locale-namespace-key:value)                                                                                                                                                                   |    No    |
| namespaceGlob           | string\|string[]                                     | Glob for namespace(s) to process, useful to include or exclude some files, learn more [glob](https://www.npmjs.com/package/glob#usage)                                                                                                                                                         |    No    |
| openAIApiUrl            | string                                               | Optional base url of OpenAI API, useful with proxy                                                                                                                                                                                                                                             |    No    |
| openAIApiUrlPath        | string                                               | Optional URL endpoint of OpenAI API, useful with proxy                                                                                                                                                                                                                                         |    No    |
| modelContextLimit       | number                                               | Optional max context window that the model supports. For example for gpt-4-32k, the context is 32768 tokens. Default to 4096 (gpt-3.5-turbo)                                                                                                                                                   |    No    |
| modelContextSplit       | number                                               | Optional ratio to split between number of input / output tokens. For example, if the input language is English and output is Spanish, you may expect 1 input token to produce 2 output tokens. In this case, the variable is set to 1/2. By default, modelContextSplit is set to 1/1           |    No    |
| systemPromptTemplate    | function                                             | (For advanced usage) Custom prompt template. See "translate.ts" for the default prompt.                                                                                                                                                                                                        |    No    |
| additionalReqBodyParams | any                                                  | (For advanced usage) Custom parameters to be passed into request body. Useful if you use a self-hosted model and you want to customize model parameters. For example, see [llama.cpp server example](https://github.com/ggerganov/llama.cpp/tree/master/examples/server)                       |    No    |
| singleFileMode  | boolean | singleFileMode will use a single file for all namespaces. For example, if you have a single file `en.json` and you want to translate it to `zh.json`, you can set `singleFileMode` to true. This will translate it to `zh.json` . In this mode, the `namespace` will be ignored and set to `app`. |    No    |

## Contributing

To contribute to Transmart,refer to [contributing.md](./CONTRIBUTING.md)

## Inspired by

- https://chatgpt-i18n.vercel.app/
- https://twitter.com/forgebitz/status/1634100746617597955
- https://github.com/yetone/openai-translator


================================================
FILE: commitlint.config.js
================================================
module.exports = {
  extends: ['@commitlint/config-conventional'],
}


================================================
FILE: examples/README.md
================================================
This Folder contain All examples using transmart

Since we need to use the OpenAI API key, we need to load it into the environment variable.

Run in root of the transmart project

```sh
cp .env.example .env
```

Please enter your API key and API proxy URL (the latter is optional).

```sh
source .env
```


================================================
FILE: examples/chrome-extension/README.md
================================================


================================================
FILE: examples/chrome-extension/_locales/en/messages.json
================================================
{
  "name": {
    "message": "News Reader",
    "description": "Extension name in manifest."
  },
  "description": {
    "message": "Displays the first 5 items from the '$Google$ News - top news' RSS feed in a popup.",
    "description": "Extension description in manifest.",
    "placeholders": {
      "google": {
        "content": "Google",
        "example": "Google"
      }
    }
  },
  "default_title": {
    "message": "$Google$ News",
    "description": "Extension browser action tooltip text in manifest.",
    "placeholders": {
      "google": {
        "content": "Google",
        "example": "Google"
      }
    }
  },
  "unknown_title": {
    "message": "Unknown title",
    "description": "Unknown news title."
  },
  "error": {
    "message": "Error: $error$",
    "description": "Generic error template. Expects error parameter to be passed in.",
    "placeholders": {
      "error": {
        "content": "$1",
        "example": "Failed to fetch RSS feed."
      }
    }
  },
  "failed_to_fetch_rss": {
    "message": "Failed to fetch RSS feed.",
    "description": "User visible error message."
  },
  "not_a_valid_feed": {
    "message": "Not a valid feed.",
    "description": "User visible error message."
  },
  "more_stories": {
    "message": "To $Google$ News \u00BB",
    "description": "Link name to more Google News.",
    "placeholders": {
      "google": {
        "content": "Google",
        "example": "Google"
      }
    }
  },
  "newsUrl": {
    "message": "http://news.google.com",
    "description": "Url to Google News."
  }
}



================================================
FILE: examples/chrome-extension/feed.html
================================================
<!DOCTYPE html>
<html>
<head>
<style>
body {
  font-family: helvetica, arial, sans-serif;
  font-size: 12px;
  overflow: hidden;
}

a {
  color:#0000CC;
  text-decoration: underline;
  cursor: pointer;
}

.open_box {
  display: block;
  overflow: hidden;
  margin-right: 4px;
  margin-top: 2px;
  height: 12px;
  width: 12px;
  float: left;
  clear: left;
  background-image: url(sprite_arrows.gif);
  background-position: 0px -24px;
  cursor: pointer;
}

.opened .open_box {
  background-position:-12px -24px;
}

.item {
  padding: 2px 0px;
}

.item_title {
  display: block;
  min-width: 300px;
  padding-left: 15px;
  cursor: pointer;
}

.item_desc {
  min-width: 500px;
  height: 0px;
  display: block;
  border: none;
  padding: 0px;
  margin: 0px;
  transition: height 0.2s ease-out;
}

#title {
  display: block;
  margin-left: auto;
}

.error {
  white-space: nowrap;
  color: red;
}

.more {
  display: block;
  text-align: right;
  padding-top: 20px;
  padding-right: 10px;
  color: #88C;
}

</style>
<script id="iframe_script">
function reportHeight() {
  var msg = JSON.stringify({type:"size", size:document.body.offsetHeight});
  parent.postMessage(msg, "*");
}

function frameLoaded() {
  var links = document.getElementsByTagName("A");
  for (i = 0; i < links.length; i++) {
    var class = links[i].className;
    if (class != "item_title" && class != "open_box") {
      links[i].addEventListener("click", showStory);
    }
  }
  window.addEventListener("message", messageHandler);
}

function showStory(event) {
  var href = event.currentTarget.href;
  parent.postMessage(JSON.stringify({type:"show", url:href}), "*");
  event.preventDefault();
}

function messageHandler(event) {
  reportHeight();
}

</script>
<script>
// Feed URL.
var feedUrl = chrome.i18n.getMessage('newsUrl') + '/?output=rss';

// The XMLHttpRequest object that tries to load and parse the feed.
var req;

function main() {
  req = new XMLHttpRequest();
  req.onload = handleResponse;
  req.onerror = handleError;
  req.open("GET", feedUrl, true);
  req.send(null);
}

// Handles feed parsing errors.
function handleFeedParsingFailed(error) {
  var feed = document.getElementById("feed");
  feed.className = "error";
  feed.innerText = chrome.i18n.getMessage("error", error);
}

// Handles errors during the XMLHttpRequest.
function handleError() {
  handleFeedParsingFailed(chrome.i18n.getMessage('failed_to_fetch_rss'));
}

// Handles parsing the feed data we got back from XMLHttpRequest.
function handleResponse() {
  var doc = req.responseXML;
  if (!doc) {
    handleFeedParsingFailed(chrome.i18n.getMessage('not_a_valid_feed'));
    return;
  }
  buildPreview(doc);
}

// The maximum number of feed items to show in the preview.
var maxFeedItems = 5;

// Where the more stories link should navigate to.
var moreStoriesUrl;

function buildPreview(doc) {
  // Get the link to the feed source.
  var link = doc.getElementsByTagName("link");
  var parentTag = link[0].parentNode.tagName;
  if (parentTag != "item" && parentTag != "entry") {
    moreStoriesUrl = link[0].textContent;
  }

  // Setup the title image.
  var images = doc.getElementsByTagName("image");
  var titleImg;
  if (images.length != 0) {
    var urls = images[0].getElementsByTagName("url");
    if (urls.length != 0) {
      titleImg = urls[0].textContent;
    }
  }
  var img = document.getElementById("title");
  if (titleImg) {
    img.src = titleImg;
    if (moreStoriesUrl) {
      document.getElementById("title_a").addEventListener("click", moreStories);
    }
  } else {
    img.style.display = "none";
  }

  // Construct the iframe's HTML.
  var iframe_src = "<!doctype html><html><head><script>" +
                   document.getElementById("iframe_script").textContent + "<" +
                   "/script></head><body onload='frameLoaded();' " +
                   "style='padding:0px;margin:0px;'>";

  var feed = document.getElementById("feed");
  var entries = doc.getElementsByTagName('entry');
  if (entries.length == 0) {
    entries = doc.getElementsByTagName('item');
  }
  var count = Math.min(entries.length, maxFeedItems);
  for (var i = 0; i < count; i++) {
    item = entries.item(i);

    // Grab the title for the feed item.
    var itemTitle = item.getElementsByTagName('title')[0];
    if (itemTitle) {
      itemTitle = itemTitle.textContent;
    } else {
      itemTitle = chrome.i18n.getMessage("unknown_title");
    }

    // Grab the description.
    var itemDesc = item.getElementsByTagName('description')[0];
    if (!itemDesc) {
      itemDesc = item.getElementsByTagName('summary')[0];
      if (!itemDesc) {
        itemDesc = item.getElementsByTagName('content')[0];
      }
    }
    if (itemDesc) {
      itemDesc = itemDesc.childNodes[0].nodeValue;
    } else {
      itemDesc = '';
    }

    var item = document.createElement("div");
    item.className = "item";
    var box = document.createElement("div");
    box.className = "open_box";
    box.addEventListener("click", showDesc);
    item.appendChild(box);

    var title = document.createElement("a");
    title.className = "item_title";
    title.innerText = itemTitle;
    title.addEventListener("click", showDesc);
    item.appendChild(title);

    var desc = document.createElement("iframe");
    desc.scrolling = "no";
    desc.className = "item_desc";
    item.appendChild(desc);
    feed.appendChild(item);

    // The story body is created as an iframe with a data: URL in order to
    // isolate it from this page and protect against XSS.  As a data URL, it
    // has limited privileges and must communicate back using postMessage().
    desc.src="data:text/html," + iframe_src + itemDesc + "</body></html>";
  }

  if (moreStoriesUrl) {
    var more = document.createElement("a");
    more.className = "more";
    more.innerText = chrome.i18n.getMessage("more_stories");
    more.addEventListener("click", moreStories);
    feed.appendChild(more);
  }
}

// Show |url| in a new tab.
function showUrl(url) {
  // Only allow http and https URLs.
  if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) {
    return;
  }
  chrome.tabs.create({url: url});
}

function moreStories(event) {
  showUrl(moreStoriesUrl);
}

function showDesc(event) {
  var item = event.currentTarget.parentNode;
  var items = document.getElementsByClassName("item");
  for (var i = 0; i < items.length; i++) {
    var iframe = items[i].getElementsByClassName("item_desc")[0];
    if (items[i] == item && items[i].className == "item") {
      items[i].className = "item opened";
      iframe.contentWindow.postMessage("reportHeight", "*");
    } else {
      items[i].className = "item";
      iframe.style.height = "0px";
    }
  }
}

function iframeMessageHandler(e) {
  // Only listen to messages from one of our own iframes.
  var iframes = document.getElementsByTagName("IFRAME");
  for (var i = 0; i < iframes.length; i++) {
    if (iframes[i].contentWindow == e.source) {
      var msg = JSON.parse(e.data);
      if (msg) {
        if (msg.type == "size") {
          iframes[i].style.height = msg.size + "px";
        } else if (msg.type == "show") {
          var url = msg.url;
          if (url.indexOf(chrome.i18n.getMessage('newsUrl')) == 0) {
            // If the URL is a redirect URL, strip of the destination and go to
            // that directly.  This is necessary because the Google news
            // redirector blocks use of the redirects in this case.
            var index = url.indexOf("&url=");
            if (index >= 0) {
              url = url.substring(index + 5);
              index = url.indexOf("&");
              if (index >= 0)
                url = url.substring(0, index);
            }
          }
          showUrl(url);
        }
      }
      return;
    }
  }
}

window.addEventListener("message", iframeMessageHandler);
</script>
</head>
<body onload="main();">
<a id="title_a"><img id='title'></a>
<div id="feed"></div>
</body>
</html>


================================================
FILE: examples/chrome-extension/manifest.json
================================================
{
  "name": "__MSG_name__",
  "version": "1.1",
  "description": "__MSG_description__",
  "icons": { "128": "news_icon.png" },
  "browser_action": {
    "default_title": "__MSG_default_title__",
    "default_icon": "news_action.png",
    "default_popup": "feed.html"
  },
  "permissions": [
    "tabs",
    "http://news.google.com/*",
    "http://news.google.es/*"
  ],
  "default_locale": "en"
}


================================================
FILE: examples/chrome-extension/package.json
================================================
{
  "name": "chrome-extension",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "translate": "transmart"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@transmart/cli": "^0.0.3"
  }
}


================================================
FILE: examples/chrome-extension/transmart.config.js
================================================
// eslint-disable-next-line @typescript-eslint/no-var-requires

module.exports = {
  baseLocale: 'en',
  locales: ['zh_CN', 'pt_BR', 'es_419'],
  localePath: '_locales',
  openAIApiKey: process.env.OPENAI_API_KEY,
  openAIApiUrl: process.env.OPENAI_API_URL,
}


================================================
FILE: examples/next.js/@types/i18next.d.ts
================================================
/**
 * If you want to enable locale keys typechecking and enhance IDE experience.
 *
 * Requires `resolveJsonModule:true` in your tsconfig.json.
 *
 * @link https://www.i18next.com/overview/typescript
 */
import 'i18next'

import type common from '../public/locales/en/common.json'
import type footer from '../public/locales/en/footer.json'
import type secondPage from '../public/locales/en/second-page.json'

interface I18nNamespaces {
  common: typeof common
  footer: typeof footer
  'second-page': typeof secondPage
}

declare module 'i18next' {
  interface CustomTypeOptions {
    defaultNS: 'common'
    resources: I18nNamespaces
  }
}


================================================
FILE: examples/next.js/components/Footer.tsx
================================================
import pkg from 'next-i18next/package.json'
import { useTranslation, Trans } from 'next-i18next'
import type { FC } from 'react'

export const Footer: FC = () => {
  const { t } = useTranslation('footer')

  return (
    <footer>
      <p>{t('description')}</p>
      <p>next-i18next v{pkg.version}</p>
      <p
        style={{
          fontSize: 'smaller',
          fontStyle: 'italic',
          marginTop: 20,
        }}
      >
        <Trans i18nKey="helpLocize" t={t}>
          With using
          <a href="https://locize.com" target="_new">
            locize
          </a>
          you directly support the future of
          <a href="https://www.i18next.com" target="_new">
            i18next
          </a>
          .
        </Trans>
      </p>
    </footer>
  )
}


================================================
FILE: examples/next.js/components/Header.tsx
================================================
import Head from 'next/head'
import type { FC } from 'react'

type Props = {
  heading: string
  title: string
}

export const Header: FC<Props> = ({ heading, title }) => (
  <>
    <Head>
      <title>{title}</title>
    </Head>
    <h2>
      next-i18next
      <hr />
    </h2>
    <h1>{heading}</h1>
    <a className="github" href="//github.com/i18next/next-i18next">
      <i className="typcn typcn-social-github-circular" />
    </a>
  </>
)


================================================
FILE: examples/next.js/next-env.d.ts
================================================
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.


================================================
FILE: examples/next.js/next-i18next.config.js
================================================
// @ts-check

/**
 * @type {import('next-i18next').UserConfig}
 */
module.exports = {
  // https://www.i18next.com/overview/configuration-options#logging
  debug: process.env.NODE_ENV === 'development',
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'de', 'fr', 'es', 'zh', 'ja', 'ko', 'pt', 'it', 'ru'],
  },
  /** To avoid issues when deploying to some paas (vercel...) */
  localePath: typeof window === 'undefined' ? require('path').resolve('./public/locales') : '/locales',

  reloadOnPrerender: process.env.NODE_ENV === 'development',

  /**
   * @link https://github.com/i18next/next-i18next#6-advanced-configuration
   */
  // saveMissing: false,
  // strictMode: true,
  // serializeConfig: false,
  // react: { useSuspense: false }
}


================================================
FILE: examples/next.js/next-utils.config.js
================================================
const pc = require('picocolors')

const nextUtilsConfig = () => {
  const trueEnv = ['true', '1', 'yes']
  const esmExternals = trueEnv.includes(process.env?.NEXTJS_ESM_EXTERNALS ?? 'false')
  const tsconfigPath = process.env.NEXTJS_TSCONFIG_PATH ? process.env.NEXTJS_TSCONFIG_PATH : './tsconfig.json'

  // eslint-disable-next-line no-console
  console.warn(`${pc.green('warn  -')} experimental.esmExternals is ${esmExternals ? 'enabled' : 'disabled'}`)
  return {
    esmExternals,
    tsconfigPath,
  }
}

module.exports = {
  loadCustomBuildParams: nextUtilsConfig,
}


================================================
FILE: examples/next.js/next.config.js
================================================
// @ts-check
const { i18n } = require('./next-i18next.config.js')

// You can remove the following 2 lines when integrating our example.
const { loadCustomBuildParams } = require('./next-utils.config')
const { esmExternals = false, tsconfigPath } =
  loadCustomBuildParams()

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    esmExternals, // https://nextjs.org/blog/next-11-1#es-modules-support
  },
  i18n,
  reactStrictMode: true,
  typescript: {
    tsconfigPath,
  },
}

module.exports = nextConfig


================================================
FILE: examples/next.js/package.json
================================================
{
  "name": "v12",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start -p ${PORT:=3000}",
    "typecheck": "tsc --project ./tsconfig.json --noEmit",
    "clean": "rimraf .next",
    "translate": "transmart",
    "nuke:install": "rimraf ./node_modules ./package-lock.json"
  },
  "dependencies": {
    "@transmart/cli": "^0.0.3",
    "i18next": "^22.4.11",
    "next": "^13.2.4",
    "next-i18next": "^13.2.2",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-i18next": "^12.2.0"
  },
  "devDependencies": {
    "@types/node": "^18.15.0",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "eslint-config-next": "^13.2.4",
    "picocolors": "^1.0.0",
    "rimraf": "^4.4.0",
    "typescript": "^4.9.5"
  }
}


================================================
FILE: examples/next.js/pages/_app.tsx
================================================
import type { AppProps } from 'next/app'
import { appWithTranslation } from 'next-i18next'
// import nextI18NextConfig from '../next-i18next.config.js'

const MyApp = ({ Component, pageProps }: AppProps) => (
  <Component {...pageProps} />
)

// https://github.com/i18next/next-i18next#unserializable-configs
export default appWithTranslation(MyApp /*, nextI18NextConfig */)


================================================
FILE: examples/next.js/pages/_document.tsx
================================================
import Document, {
  Html,
  Head,
  Main,
  NextScript,
} from 'next/document'
import type { DocumentProps } from 'next/document'
import i18nextConfig from '../next-i18next.config'

type Props = DocumentProps & {
  // add custom document props
}

class MyDocument extends Document<Props> {
  render() {
    const currentLocale =
      this.props.__NEXT_DATA__.locale ??
      i18nextConfig.i18n.defaultLocale
    return (
      <Html lang={currentLocale}>
        <Head>
          <meta charSet="utf-8" />
          <link
            href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"
            rel="stylesheet"
          />
          <link href="/app.css" rel="stylesheet" />
          <link
            href="https://cdnjs.cloudflare.com/ajax/libs/typicons/2.0.9/typicons.min.css"
            rel="stylesheet"
          />
          <link
            href="https://fonts.googleapis.com/css?family=Open+Sans:300,400|Oswald:600"
            rel="stylesheet"
          />
          <link
            data-react-helmet="true"
            rel="icon"
            href="https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/spaces%2F-L9iS6Wm2hynS5H9Gj7j%2Favatar.png?generation=1523462254548780&amp;alt=media"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument


================================================
FILE: examples/next.js/pages/index.tsx
================================================
import Link from 'next/link'
import { useRouter } from 'next/router'
import type { GetStaticProps, InferGetStaticPropsType, GetServerSideProps } from 'next'

import { useTranslation, Trans } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'

import { Header } from '../components/Header'
import { Footer } from '../components/Footer'

type Props = {
  // Add custom props here
}

const Homepage = (_props: InferGetStaticPropsType<typeof getServerSideProps>) => {
  const router = useRouter()
  const { t } = useTranslation('common')
  const { changeTo } = _props
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const onToggleLanguageClick = (newLocale: string) => {
    const { pathname, asPath, query } = router
    router.push({ pathname, query }, asPath, { locale: newLocale })
  }

  return (
    <>
      <main>
        <Header heading={t('h1')} title={t('title')} />
        <div style={{ display: 'inline-flex', width: '90%' }}>
          <div style={{ width: '33%' }}>
            <h3 style={{ minHeight: 70 }}>{t('blog.appDir.question')}</h3>
            <p>
              <Trans i18nKey="blog.appDir.answer">
                Then check out
                <a href={t('blog.optimized.link')}>this blog post</a>.
              </Trans>
            </p>
            <a href={t('blog.appDir.link')}>
              <img
                style={{ width: '50%' }}
                src="https://locize.com/blog/next-13-app-dir-i18n/next-13-app-dir-i18n.jpg"
              />
            </a>
          </div>
          <div style={{ width: '33%' }}>
            <h3 style={{ minHeight: 70 }}>{t('blog.optimized.question')}</h3>
            <p>
              <Trans i18nKey="blog.optimized.answer">
                Then you may have a look at
                <a href={t('blog.optimized.link')}>this blog post</a>.
              </Trans>
            </p>
            <a href={t('blog.optimized.link')}>
              <img style={{ width: '50%' }} src="https://locize.com/blog/next-i18next/next-i18next.jpg" />
            </a>
          </div>
          <div style={{ width: '33%' }}>
            <h3 style={{ minHeight: 70 }}>{t('blog.ssg.question')}</h3>
            <p>
              <Trans i18nKey="blog.ssg.answer">
                Then you may have a look at
                <a href={t('blog.ssg.link')}>this blog post</a>.
              </Trans>
            </p>
            <a href={t('blog.ssg.link')}>
              <img style={{ width: '50%' }} src="https://locize.com/blog/next-i18n-static/title.jpg" />
            </a>
          </div>
        </div>
        <hr style={{ marginTop: 20, width: '90%' }} />
        <div>
          <Link href="/" locale={changeTo}>
            <button>{t('change-locale', { changeTo })}</button>
          </Link>
          {/* alternative language change without using Link component
          <button onClick={() => onToggleLanguageClick(changeTo)}>
            {t('change-locale', { changeTo })}
          </button>
          */}
          <Link href="/second-page">
            <button type="button">{t('to-second-page')}</button>
          </Link>
        </div>
      </main>
      <Footer />
    </>
  )
}

// or getServerSideProps: GetServerSideProps<Props> = async ({ locale })
export const getServerSideProps: GetServerSideProps<Props> = async ({ locale, locales }) => ({
  props: {
    changeTo: (locales || [])[Math.floor(Math.random() * (locales || [])?.length)],
    ...(await serverSideTranslations(locale ?? 'en', ['common', 'footer'])),
  },
})

export default Homepage


================================================
FILE: examples/next.js/pages/second-page.tsx
================================================
import Link from 'next/link'
import type {
  GetServerSideProps,
  InferGetServerSidePropsType,
} from 'next'

import { useTranslation } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'

import { Header } from '../components/Header'
import { Footer } from '../components/Footer'

type Props = {
  // Add custom props here
}

const SecondPage = (
  _props: InferGetServerSidePropsType<typeof getServerSideProps>
) => {
  const { t } = useTranslation(['common', 'second-page'])

  return (
    <>
      <main>
        <Header
          heading={t('second-page:h1')}
          title={t('second-page:title')}
        />
        <Link href="/">
          <button type="button">
            {t('second-page:back-to-home')}
          </button>
        </Link>
      </main>
      <Footer />
    </>
  )
}

export const getServerSideProps: GetServerSideProps<Props> = async ({
  locale,
}) => ({
  props: {
    ...(await serverSideTranslations(locale ?? 'en', [
      'second-page',
      'footer',
    ])),
  },
})

export default SecondPage


================================================
FILE: examples/next.js/public/app.css
================================================
#__next {
  font-family: 'Open Sans', sans-serif;
  text-align: center;
  background-image: linear-gradient(
    to left top,
    #ffffff,
    #f5f5f5,
    #eaeaea,
    #e0e0e0,
    #d6d6d6
  );
  display: flex;
  flex-direction: column;
  margin: 0;
  min-height: 100vh;
  min-width: 100vw;
}

h1,
h2 {
  font-family: 'Oswald', sans-serif;
}

h1 {
  font-size: 3rem;
  margin: 5rem 0;
}
h2 {
  min-width: 18rem;
  font-size: 2rem;
  opacity: 0.3;
}
h3 {
  font-size: 1.5rem;
  opacity: 0.5;
}

p {
  line-height: 1.65em;
}
p:nth-child(2) {
  font-style: italic;
  opacity: 0.65;
  margin-top: 1rem;
}

a.github {
  position: fixed;
  top: 0.5rem;
  right: 0.75rem;
  font-size: 4rem;
  color: #888;
  opacity: 0.8;
}
a.github:hover {
  opacity: 1;
}

button {
  display: inline-block;
  vertical-align: bottom;
  outline: 0;
  text-decoration: none;
  cursor: pointer;
  background-color: rgba(255, 255, 255, 0.5);
  box-sizing: border-box;
  font-size: 1em;
  font-family: inherit;
  border-radius: 3px;
  transition: box-shadow 0.2s ease;
  user-select: none;
  line-height: 2.5em;
  min-height: 40px;
  padding: 0 0.8em;
  border: 0;
  color: inherit;
  position: relative;
  transform: translateZ(0);
  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
  margin: 0.8rem;
}

button:hover,
button:focus {
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4);
}

main {
  display: flex;
  flex-direction: column;
  flex: 1;
  justify-content: center;
  align-items: center;
}
footer {
  background-color: rgba(255, 255, 255, 0.5);
  width: 100vw;
  padding: 3rem 0;
}


================================================
FILE: examples/next.js/public/locales/en/common.json
================================================
{
  "h1": "A simple example",
  "change-locale": "Change locale to \"{{changeTo}}\"",
  "to-second-page": "To second page",
  "error-with-status": "A {{statusCode}} error occurred on server",
  "error-without-status": "An error occurred on the server",
  "title": "Home | next-i18next",
  "blog": {
    "appDir": {
      "question": "Are you using the new Next.js 13 app directory?",
      "answer": "Then check out <1>this blog post</1>.",
      "link": "https://locize.com/blog/next-13-app-dir-i18n/"
    },
    "optimized": {
      "question": "Do you like to unleash some super powers to have all side optimized translations?",
      "answer": "Then you may have a look at <1>this blog post</1>.",
      "link": "https://locize.com/blog/next-i18next/"
    },
    "ssg": {
      "question": "Do you want to use SSG (next export)?",
      "answer": "Then you may have a look at <1>this blog post</1>.",
      "link": "https://locize.com/blog/next-i18n-static/"
    }
  }
}


================================================
FILE: examples/next.js/public/locales/en/footer.json
================================================
{
  "description": "This is a non-page component that requires its own namespace",
  "helpLocize": "With using <1>locize</1> you directly support the future of <3>i18next</3>."
}


================================================
FILE: examples/next.js/public/locales/en/second-page.json
================================================
{
  "h1": "A second page, to demonstrate routing",
  "back-to-home": "Back to home",
  "title": "Second page | next-i18next"
}


================================================
FILE: examples/next.js/transmart.config.js
================================================
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { i18n } = require('./next-i18next.config.js')

module.exports = {
  baseLocale: 'en',
  locales: i18n.locales, // avoid duplicated
  localePath: 'public/locales',
  openAIApiKey: process.env.OPENAI_API_KEY,
  openAIApiUrl: process.env.OPENAI_API_URL,
}


================================================
FILE: examples/next.js/tsconfig.json
================================================
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "target": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "baseUrl": ".",
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "**/*.js",
    "**/*.jsx",
    "**/*.cjs",
    "**/*.mjs"
  ],
  "exclude": ["**/node_modules", "**/.*/"]
}


================================================
FILE: examples/next.js/vercel.json
================================================
{
  "github": {
    "silent": true
  }
}


================================================
FILE: lerna.json
================================================
{
  "$schema": "node_modules/lerna/schemas/lerna-schema.json",
  "useWorkspaces": true,
  "version": "0.5.3",
  "registry": "https://registry.npmjs.org/"
}


================================================
FILE: package.json
================================================
{
  "name": "transmart",
  "version": "0.0.1",
  "main": "lib/index.js",
  "typings": "lib/index.d.ts",
  "description": "Automate your i18n localization with AI",
  "files": [
    "lib"
  ],
  "workspaces": [
    "packages/*"
  ],
  "keywords": [
    "i18n",
    "translation",
    "ChatGPT",
    "AI"
  ],
  "scripts": {
    "clean": "lerna run clean",
    "build": "lerna run build",
    "build:watch": "lerna run build:watch",
    "typecheck": "tsc",
    "typecheck:watch": "tsc --watch",
    "lint": "eslint --quiet packages --ext .ts",
    "lint:fix": "eslint --quiet --fix packages --ext .ts",
    "bootstrap": "source .env",
    "release": "npm run clean && npm run build && lerna publish"
  },
  "dependencies": {
    "commander": "^9.4.1",
    "fs-extra": "^11.1.0",
    "node-fetch": "^2.6.9",
    "spinnies": "^0.5.1"
  },
  "devDependencies": {
    "@commitlint/cli": "^12.1.4",
    "@commitlint/config-conventional": "^12.1.4",
    "@types/fs-extra": "^9.0.13",
    "@types/node": "^18.15.0",
    "@types/node-fetch": "^2.6.2",
    "@types/prettier": "^2.7.1",
    "@types/spinnies": "^0.5.0",
    "@typescript-eslint/eslint-plugin": "^4.26.0",
    "@typescript-eslint/parser": "^4.26.0",
    "eslint": "^7.27.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^3.4.0",
    "husky": "^4.3.8",
    "lerna": "^6.5.1",
    "lint-staged": "^11.0.0",
    "prettier": "2.3.0",
    "typescript": "^4.9.5"
  },
  "lint-staged": {
    "**/*.{ts,tsx,js,jsx}": [
      "eslint --fix"
    ],
    "**/!README.md": [
      "prettier --write"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run typecheck && lint-staged --debug",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  }
}


================================================
FILE: packages/cli/README.md
================================================
[Docs](https://github.com/Quilljou/transmart)


================================================
FILE: packages/cli/bin/transmart.js
================================================
#!/usr/bin/env node

require('../lib/index')


================================================
FILE: packages/cli/package.json
================================================
{
  "name": "@transmart/cli",
  "version": "0.5.3",
  "main": "lib/index.js",
  "typings": "lib/index.d.ts",
  "files": [
    "lib",
    "bin",
    "README.md"
  ],
  "bin": {
    "transmart": "bin/transmart.js"
  },
  "publishConfig": {
    "access": "public"
  },
  "scripts": {
    "clean": "rm -rf ./lib",
    "build": "npm run clean && tsc -p tsconfig.build.json",
    "build:watch": "npm run clean && tsc -p tsconfig.build.json --watch"
  },
  "dependencies": {
    "@transmart/core": "^0.5.3",
    "@types/spinnies": "^0.5.0",
    "commander": "^9.4.1",
    "cosmiconfig": "^8.3.6",
    "cosmiconfig-typescript-loader": "^5.0.0",
    "fs-extra": "^11.1.0",
    "spinnies": "^0.5.1"
  },
  "devDependencies": {
    "@types/fs-extra": "^9.0.13",
    "@types/node": "^18.15.0",
    "@types/node-fetch": "^2.6.2",
    "typescript": "^4.9.5"
  }
}


================================================
FILE: packages/cli/src/cli.ts
================================================
import { CmdOptions } from './types'
import { Transmart } from '@transmart/core'
import * as fs from 'fs-extra'
import * as path from 'path'
import * as Spinnies from 'spinnies'

export async function run(options: CmdOptions) {
  const transmart = new Transmart(options)
  const spinnerManager = new Spinnies()
  const result = await transmart.run({
    onStart(work) {
      const key = work.locale + '-' + path.basename(work.inputNSFilePath)
      spinnerManager.add(key, { text: key + ' translating...' })
    },
    onProgress(current, total, work) {
      const key = work.locale + '-' + path.basename(work.inputNSFilePath)
      spinnerManager.update(key, { text: key + ' translating...' + `(${current}/${total})` })
    },
    onResult(result) {
      const { work, failed, content, reason } = result
      const key = work.locale + '-' + path.basename(work.inputNSFilePath)
      if (failed) {
        spinnerManager.fail(key, { text: key + ' failed: ' + reason?.message })
      } else if (content) {
        const dirname = path.dirname(work.outputNSFilePath)
        fs.mkdirpSync(dirname)
        fs.writeFileSync(work.outputNSFilePath, content, {
          encoding: 'utf-8',
        })
        spinnerManager.succeed(key, { text: key + ' translated' })
      }
    },
  })

  console.log(
    `\n Transmart complete!\n Total: ${result.namespaces.total}\n Success: ${result.namespaces.success} \n Failed: ${result.namespaces.failed}`,
  )
  return result
}


================================================
FILE: packages/cli/src/index.ts
================================================
import { parseArgv } from './options'
import { run } from './cli'

parseArgv(process.argv).then((opts) => {
  if (opts) {
    run(opts).catch((err) => {
      console.error(err)
      process.exitCode = 1
    })
  } else {
    process.exitCode = 2
  }
})


================================================
FILE: packages/cli/src/options.ts
================================================
import { CmdOptions } from './types'
import { program } from 'commander'
import { cosmiconfig } from 'cosmiconfig'
import { TypeScriptLoader } from 'cosmiconfig-typescript-loader'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pkg = require('../package.json')

program
  .description(
    `🚀 Automate your i18n localization with AI.
  \n Example: \n\n npx transmart (transmart.config.js must be present)
  \n Or more verbose way: \n\n npx transmart -b en-US -p public/locales -l zh-CN,jp,de -k <your-own-openai-api-key>`,
  )
  .option(
    '-c, --config <configurationFile>',
    'transmart.config.js or transmartrc.json whatever config file format which cosmiconfig supports',
  )
  .option(
    '-b, --base-locale <baseLocale>',
    'the language that Transmart will use as a reference to translate other target languages',
  )
  .option(
    '-l, --locales <locales...>',
    'all the languages that need to be translated (including baseLocale which is also acceptable)',
  )
  .option('-p, --locale-path <localePath>', 'where you store your locale files')
  .option(
    '-k, --openAI-api-key <openAIApiKey>',
    'the OpenAI API Key. For instructions on how to obtain a key, please refer to: https://gptforwork.com/setup/how-to-create-openai-api-key',
  )
  .option('--context <context>', 'Provide some context for a more accurate translation.')
  .option('--openAI-api-url <openAIApiUrl>', 'OpenAI API base url, useful when using proxy')
  .option('--openAI-api-urlpath <openAIApiUrlPath>', 'OpenAI API url endpoint, which is useful when using proxy')
  .option('--openAI-api-model <openAIApiModel>', 'OpenAI API model, default to`gpt-3.5-turbo`')
  .option('-n, --namespace-glob <namespaceGlobs...>', 'glob pattern(s) to match namespace(s)')
  .option(
    '-s, --single-file-mode <singleFileMode>',
    'single file mode indicts such as zh.json translate to en.json, default to false',
  )
  .version(pkg.version)
  .parse()

const explorer = cosmiconfig('transmart', {
  loaders: {
    '.ts': TypeScriptLoader(),
  },
})

export async function parseArgv(args: Array<string>): Promise<CmdOptions | null> {
  const stdInOptions = program.opts<CmdOptions>()
  let consmiconResult
  try {
    consmiconResult = stdInOptions.config ? await explorer.load(stdInOptions.config) : await explorer.search()
  } catch (error) {
    console.error(error)
    // do nothing
    if (!stdInOptions.config) {
      throw new Error('please provide a valid config file')
    }
  }
  if (consmiconResult) {
    return Object.assign(consmiconResult.isEmpty ? {} : consmiconResult.config, stdInOptions)
  }
  return stdInOptions
}


================================================
FILE: packages/cli/src/types.ts
================================================
import { TransmartOptions } from '@transmart/core'

export type CmdOptions = TransmartOptions & {
  config: string
}


================================================
FILE: packages/cli/tsconfig.build.json
================================================
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "noEmit": false,
    "module": "CommonJS",
    "outDir": "lib",
    "rootDir": "./src",
    "baseUrl": "./",
    "allowSyntheticDefaultImports": true
  },
  "include": ["./src"]
}


================================================
FILE: packages/core/README.md
================================================
[Docs](https://github.com/Quilljou/transmart)


================================================
FILE: packages/core/package.json
================================================
{
  "name": "@transmart/core",
  "version": "0.5.3",
  "main": "lib/index.js",
  "typings": "lib/index.d.ts",
  "files": [
    "lib"
  ],
  "publishConfig": {
    "access": "public"
  },
  "scripts": {
    "clean": "rm -rf ./lib",
    "build": "npm run clean && tsc -p tsconfig.build.json",
    "build:watch": "npm run clean && tsc -p tsconfig.build.json --watch"
  },
  "dependencies": {
    "@types/glob": "^8.1.0",
    "fs-extra": "^11.1.0",
    "glob": "^9.3.0",
    "gpt-3-encoder": "^1.1.4",
    "gpt3-tokenizer": "^1.1.5",
    "jsonrepair": "^3.6.0",
    "node-fetch": "^2.6.9",
    "p-limit": "^3.1.0"
  },
  "devDependencies": {
    "@types/fs-extra": "^9.0.13",
    "@types/node": "^18.15.0",
    "@types/node-fetch": "^2.6.2",
    "typescript": "^4.9.5"
  }
}


================================================
FILE: packages/core/src/index.ts
================================================
export { Transmart } from './transmart'
export * from './types'


================================================
FILE: packages/core/src/language.ts
================================================
export function getLanguageDisplayName(code: string) {
  try {
    code = code.replace('_', '-') // support chrome.i18n. and Intl don't support _
    const ret = new Intl.DisplayNames(['en'], { type: 'language' }).of(code)
    if (ret === code) {
      console.warn(`the language code '${code}' can't be parsed`)
    }
    return ret
  } catch (error) {
    console.log(error)
    console.warn(`the language code '${code}' seems broken`)
    return code
  }
}


================================================
FILE: packages/core/src/limit.ts
================================================
import * as pLimit from 'p-limit'

const CONCURRENCY = 5

export const limit = pLimit(CONCURRENCY)


================================================
FILE: packages/core/src/split.ts
================================================
import { encode } from 'gpt-3-encoder'

export function splitJSONtoSmallChunks(
  object: Record<string, unknown>,
  options: { modelContextLimit: number; modelContextSplit: number },
) {
  const maxInputToken = Math.floor(options.modelContextLimit * options.modelContextSplit)
  const chunks: Record<string, unknown>[] = []
  const keys = Object.keys(object)
  const totalLength = keys.length
  let keysLength = totalLength

  let tempChunk: Record<string, unknown> = {}
  let chunkSize = 2
  while (keysLength > 0) {
    const key = keys[totalLength - keysLength]
    const value = object[key]
    const keySize = encode(key).length + 2 // "key":
    const nextValueSize = isPlainObject(value) ? getJSONTokenSize(value, 1) : getPrimitiveValueSize(value)
    const entrySize = 1 + keySize + nextValueSize // \n + "key": + value

    if (chunkSize + entrySize > maxInputToken) {
      // If temp chunk has content, save it first
      if (Object.keys(tempChunk).length > 0) {
        chunks.push({ ...tempChunk })
        tempChunk = {}
        chunkSize = 2
      }

      // If the single entry itself is too large, add it to its own chunk anyway
      // Otherwise we'd have an infinite loop
      tempChunk[key] = value
      chunks.push({ ...tempChunk })
      tempChunk = {}
      chunkSize = 2
    } else {
      tempChunk[key] = value
      chunkSize += entrySize
    }
    keysLength--
  }
  if (Object.keys(tempChunk).length) {
    chunks.push(tempChunk)
  }

  return chunks
}

export function isPlainObject(obj: unknown): obj is Record<string, unknown> {
  return Object.prototype.toString.call(obj) === '[object Object]'
}
// almost close to json
function getJSONTokenSize(object: Record<string, unknown>, depth = 0): number {
  const keys = Object.keys(object)
  const totalLength = keys.length
  let keysLength = totalLength
  let tokenCount = 1 // {

  while (keysLength > 0) {
    const key = keys[totalLength - keysLength]
    const value = object[key]
    tokenCount += 1 // \n
    tokenCount += depth * 2 // indent
    tokenCount += encode(key).length + 2 // "key":
    if (isPlainObject(value)) {
      tokenCount += getJSONTokenSize(value, depth + 1)
    } else {
      tokenCount += getPrimitiveValueSize(value)
    }
    keysLength--
  }
  tokenCount += 2 // '\n'
  tokenCount += depth // }
  return tokenCount
}

function getPrimitiveValueSize(value: any): number {
  return encode(value).length + 3 // "value",
}


================================================
FILE: packages/core/src/task.ts
================================================
import { Transmart } from './transmart'
import { RunWork } from './types'
import { readFile } from 'node:fs/promises'
import { translate } from './translate'
import { isPlainObject, splitJSONtoSmallChunks } from './split'
import { limit } from './limit'
import { jsonrepair } from 'jsonrepair'

interface TaskResult {
  content: string
  index: number
}

export class Task {
  constructor(private transmart: Transmart, private work: RunWork) {}

  async start(onProgress: (current: number, total: number) => any) {
    const { inputNSFilePath, namespace, locale } = this.work
    const { modelContextLimit, modelContextSplit } = this.transmart.options
    const content = await readFile(inputNSFilePath, { encoding: 'utf-8' })
    const chunks = splitJSONtoSmallChunks(JSON.parse(content), { modelContextLimit, modelContextSplit })
    let count = 0

    const p = chunks.map((chunk, index) => {
      return limit(() =>
        (async () => {
          const result = await this.run(JSON.stringify(chunk, null, 2), index)
          count++
          onProgress(count, chunks.length)
          return result
        })(),
      )
    })
    const results = await Promise.all(p)
    const namespaceResult = this.pack(results)
    const { overrides } = this.transmart.options

    // override with user provided
    if (overrides && isPlainObject(overrides)) {
      Object.entries(overrides).forEach(([overrideKey, value]) => {
        if (overrideKey === locale && isPlainObject(value)) {
          Object.entries(value).forEach(([overrideNs, overrideValues]) => {
            if (overrideNs === namespace) {
              Object.assign(namespaceResult, overrideValues)
            }
          })
        }
      })
    }
    return JSON.stringify(namespaceResult, null, 2)
  }

  private async run(content: string, index: number): Promise<TaskResult> {
    const {
      openAIApiKey,
      openAIApiUrl,
      openAIApiUrlPath,
      openAIApiModel,
      baseLocale,
      context,
      systemPromptTemplate,
      additionalReqBodyParams,
    } = this.transmart.options
    const { locale } = this.work

    const data = await translate({
      content,
      baseLang: baseLocale,
      targetLang: locale,
      context,
      openAIApiModel,
      openAIApiKey,
      openAIApiUrl,
      openAIApiUrlPath,
      systemPromptTemplate,
      additionalReqBodyParams,
    })
    return {
      content: data,
      index,
    }
  }

  parse(content: string): Record<string, any> {
    try {
      const parsedJson = JSON.parse(content)
      return parsedJson
    } catch (e) {
      // try fix using jsonrepair, if it still fails, just raise error
      const parsedJson = JSON.parse(jsonrepair(content))
      return parsedJson
    }
  }

  pack(result: TaskResult[]): Record<string, any> {
    const onePiece = result
      .sort((a, b) => a.index - b.index)
      .reduce((prev, next) => {
        const parsedJson = this.parse(next.content)
        return {
          ...prev,
          ...parsedJson,
        }
      }, {})
    return onePiece
  }
}


================================================
FILE: packages/core/src/translate.ts
================================================
import fetch from 'node-fetch'
import { getLanguageDisplayName } from './language'
import { TranslateParams } from './types'

export async function translate(params: TranslateParams, retryTime = 0): Promise<string> {
  const {
    baseLang,
    targetLang,
    openAIApiKey,
    retryTimes,
    openAIApiUrl,
    openAIApiUrlPath,
    content,
    openAIApiModel,
    context,
    systemPromptTemplate,
    additionalReqBodyParams,
  } = params
  const headers = {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${openAIApiKey}`,
  }
  const languageName = getLanguageDisplayName(targetLang)
  const systemPrompt = systemPromptTemplate
    ? systemPromptTemplate({ languageName, context })
    : `Translate the contents of the i18n JSON file to ${languageName} according to the BCP 47 standard, ensuring the integrity and structure of the file are preserved. Please adhere to the following guidelines:

- **Keep the keys identical to the original file** to ensure structural integrity. The translation should occur in the values only.
- **Maintain valid i18n JSON file format** throughout the translation process.
${
  context
    ? `\n**Additional contexts** are provided below to assist with a more accurate translation:---${context}---`
    : ''
}
- **Address plural forms** specifically by applying the appropriate suffixes "${getPluralSuffixes(
        baseLang,
      )}" from the base language to the corresponding "${getPluralSuffixes(
        targetLang,
      )}" suffixes in the target language ${languageName}. Accurate plural translations must be provided based on these suffixes.

Upon completion of the translation:

1. **Verify Key-Value Pairing**: Please conduct a final review to ensure that all keys remain unchanged from the original file and that each key's associated content is accurately translated and correctly placed.

2. **Validate Structure and Syntax**: Confirm that the resulting JSON structure is valid and matches the original schema, paying close attention to brackets, braces, commas, and quotes.

3. **Cross-verify Translations**: If possible, cross-reference your translations with another source or a native speaker to ensure accuracy and naturalness of the language.

The aim is to achieve a fluent and structurally sound translation of the JSON content from the base language to the target language ${languageName}, without altering the document's schema or disrupting the key-value relationship.`
  const body = {
    model: openAIApiModel,
    temperature: 0,
    messages: [
      {
        role: 'system',
        content: systemPrompt,
      },
      { role: 'user', content: `${content}` },
    ],
    ...(additionalReqBodyParams || {}),
  }
  const finalUrlPath = openAIApiUrl + openAIApiUrlPath
  const res = await fetch(finalUrlPath, {
    method: 'POST',
    headers,
    body: JSON.stringify(body),
  })
  if (res.status !== 200) {
    if (retryTime < (retryTimes || 3)) {
      return translate(params, retryTime + 1)
    }
    const { error } = await res.json()
    throw new Error(error.message)
  }
  const { choices } = await res.json()
  if (!choices || choices.length === 0) {
    throw new Error('No result')
  }
  const targetTxt = choices[0].message.content.trim()
  return findValidJSONInsideBody(targetTxt)
}

// TODO @ngxson : Sometimes, even "smart" models like GPT-4 does not understand and add a text before / after JSON
const findValidJSONInsideBody = (input: string): string => {
  const firstBracket = input.indexOf('{')
  const lastBracket = input.lastIndexOf('}') + 1
  return input.substring(firstBracket, lastBracket)
}

const getPluralSuffixes = (input: string): string =>
  new Intl.PluralRules(input)
    .resolvedOptions()
    .pluralCategories.map((cat) => `_${cat}`)
    .join(', ')


================================================
FILE: packages/core/src/transmart.ts
================================================
import * as fs from 'fs-extra'
import * as path from 'path'
import { TransmartOptions, RunOptions, RunWork, TransmartStats, Stats } from './types'
import { Task } from './task'
import { glob } from 'glob'
import { getPairHash } from './util'
import { existsSync } from 'node:fs'

const DEFAULT_PARAMS: Partial<TransmartOptions> = {
  openAIApiUrl: 'https://api.openai.com',
  openAIApiUrlPath: '/v1/chat/completions',
  openAIApiModel: 'gpt-3.5-turbo',
  modelContextLimit: 4096,
  modelContextSplit: 1 / 1,
}

export class Transmart {
  options!: Required<TransmartOptions>
  constructor(options: TransmartOptions) {
    this.options = options as Required<TransmartOptions>
  }

  public async run(options: RunOptions): Promise<TransmartStats> {
    this.validateParams()
    const {
      baseLocale,
      locales,
      localePath,
      cacheEnabled = true,
      namespaceGlob = '**/*.json',
      singleFileMode = false,
    } = this.options
    const targetLocales = locales.filter((item) => item !== baseLocale)
    const runworks: RunWork[] = []
    const baseLocaleFullPath = singleFileMode ? localePath : path.resolve(localePath, baseLocale)
    const namespaces = await glob(namespaceGlob, {
      cwd: baseLocaleFullPath,
    })
    // if cachePath is not provided, use the localePath/.cache as default
    const cachePath = this.options.cachePath || path.resolve(localePath, '.cache')
    const realNamespaces = singleFileMode ? ['app'] : namespaces
    targetLocales.forEach((targetLocale) => {
      realNamespaces.forEach((ns) => {
        const inputNSFilePath = singleFileMode
          ? path.resolve(baseLocaleFullPath, `${baseLocale}.json`)
          : path.resolve(baseLocaleFullPath, ns)
        const outputNSFilePath = singleFileMode
          ? path.resolve(baseLocaleFullPath, `${targetLocale}.json`)
          : path.resolve(localePath, targetLocale, ns)

        if (cacheEnabled) {
          const pairHash = getPairHash(inputNSFilePath, outputNSFilePath)
          const targetCachePath = path.join(cachePath, pairHash)
          // check if the cache file exists
          if (existsSync(targetCachePath) && existsSync(outputNSFilePath)) {
            console.log(`cache file and output file exists, skip for namespace ${ns} - locale ${targetLocale}`)
            return
          }
        }

        const namespace = path.parse(ns).name

        runworks.push({
          namespace: namespace,
          baseLocale,
          locale: targetLocale,
          inputNSFilePath,
          outputNSFilePath,
          cachePath,
        })
      })
    })
    const namespacesStats: Stats = {
      total: runworks.length,
      success: 0,
      failed: 0,
    }

    await Promise.all(
      runworks.map(async (work) => {
        const { onResult, onStart, onProgress } = options
        onStart?.(work)
        try {
          const task = new Task(this, work)
          const data = await task.start((current, total) => {
            onProgress?.(current, total, work)
          })
          namespacesStats.success++
          onResult?.({ work, content: data, failed: false })

          // after success, write the cache file
          if (cacheEnabled) {
            const pairHash = getPairHash(work.inputNSFilePath, work.outputNSFilePath)
            const targetCachePath = path.join(cachePath, pairHash)
            // just save an empty file as the cache file
            await fs.ensureFile(targetCachePath)
          }
        } catch (error) {
          namespacesStats.failed++
          onResult?.({ work, failed: true, content: '', reason: error as Error })
        }
      }),
    )

    // Clean up stale cache files based on existing translation outputs
    if (cacheEnabled) {
      const validHashes: string[] = []

      // For each target locale, scan its output directory for translated files
      for (const targetLocale of targetLocales) {
        const outputLocaleDir = singleFileMode ? baseLocaleFullPath : path.resolve(localePath, targetLocale)

        // Find all JSON namespaces in this locale
        const outputFiles = await glob(namespaceGlob, { cwd: outputLocaleDir })

        for (const ns of outputFiles) {
          const inputPath = singleFileMode
            ? path.resolve(baseLocaleFullPath, `${baseLocale}.json`)
            : path.resolve(baseLocaleFullPath, ns)

          const outputPath = singleFileMode
            ? path.resolve(baseLocaleFullPath, `${targetLocale}.json`)
            : path.resolve(outputLocaleDir, ns)

          // Only generate a hash if the output file actually exists
          if (await fs.pathExists(outputPath)) {
            validHashes.push(getPairHash(inputPath, outputPath))
          }
        }
      }

      // If the cache directory exists, remove any file whose name isn't in validHashes
      if (await fs.pathExists(cachePath)) {
        const entries = await fs.readdir(cachePath)
        for (const entry of entries) {
          if (!validHashes.includes(entry)) {
            await fs.remove(path.join(cachePath, entry))
            console.log(`Removed stale cache file: ${entry}`)
          }
        }
      }
    }

    return {
      namespaces: namespacesStats,
    }
  }

  private async processSingleNamespace(work: RunWork, options: RunOptions): Promise<void> {
    const { onResult, onStart, onProgress } = options
    onStart?.(work)
    try {
      const task = new Task(this, work)
      const data = await task.start((current, total) => {
        onProgress?.(current, total, work)
      })
      onResult?.({ work, content: data, failed: false })
    } catch (error) {
      onResult?.({ work, failed: true, content: '', reason: error as Error })
    }
  }

  private validateParams() {
    const { baseLocale, localePath, openAIApiKey, locales, singleFileMode = false } = this.options
    if (typeof baseLocale !== 'string') throw new Error('valid `baseLocale` must be provided')
    if (typeof openAIApiKey !== 'string') throw new Error('valid `openAIApiKey` must be provided')
    if (!Array.isArray(locales) || locales.some((i) => typeof i !== 'string'))
      throw new Error('`locales` must be Array of string')
    const baseLocaleFullPath = singleFileMode ? localePath : path.resolve(localePath, baseLocale)
    if (!fs.existsSync(baseLocaleFullPath)) throw new Error('`localePath` not existed')
    // TODO: structure
    this.options = Object.assign({}, DEFAULT_PARAMS, this.options) as Required<TransmartOptions>
  }
}


================================================
FILE: packages/core/src/types.ts
================================================
export interface TransmartOptions {
  /**
   * the language that Transmart will use as a reference to translate other target languages
   */
  baseLocale: string
  /**
   * all the languages that need to be translated (including baseLocale which is also acceptable)
   */
  locales: string[]
  /**
   * where you store your locale files
   * @example
   * - en
   *  common.json
   * - de
   *  common.json
   */
  localePath: string
  /**
   * where the cache files are stored, there will be some cache files generated during the translation process
   */
  cachePath?: string
  /**
   * whether to enable cache, default to true
   */
  cacheEnabled?: boolean
  /**
   * the OpenAI API Key. For instructions on how to obtain a key, please refer to: https://gptforwork.com/setup/how-to-create-openai-api-key
   */
  openAIApiKey: string
  /**
   * Glob for namespace(s) to process
   */
  namespaceGlob?: string | string[]
  /**
   * Provide some context for a more accurate translation.
   */
  context?: string
  /**
   * Retry times when the translation fails, default to 3
   */
  retryTimes?: number
  /**
   * OpenAI API model, default to `gpt-3.5-turbo`
   */
  openAIApiModel?: string
  /**
   * OpenAI API base url, useful when using proxy
   */
  openAIApiUrl?: string
  /**
   * OpenAI API url endpoint, which is useful when using proxy
   */
  openAIApiUrlPath?: string
  /**
   * It can be used to overwrite the generated JSON if you are not satisfied with the result of AI translation.
   * @example
   * ```js
   * {
   *  [locale]: {
   *      [namespace]: { title: "translated by hand" }
   *      chat: { title: "translated by hand" },
   *   }
   * }
   * ```
   */
  overrides?: Record<string, Record<string, Record<string, any>>>
  /**
   * The max context window that the model supports. For example for gpt-4-32k, the context is 32768 tokens. Default to 4096 (gpt-3.5-turbo)
   */
  modelContextLimit?: number
  /**
   * The ratio to split between number of input / output tokens. For example, if the input language is English and output is Spanish, you may expect 1 input token to produce 2 output tokens. In this case, the variable is set to 1/2. By default, modelContextSplit is set to 1/1
   */
  modelContextSplit?: number
  /**
   * (For advanced usage) Custom prompt template. See "translate.ts" for the default prompt.
   */
  systemPromptTemplate?: (data: { languageName: string | undefined; context: string | undefined }) => string
  /**
   * (For advanced usage) Custom parameters to be passed into request body. Useful if you use a self-hosted model and you want to customize model parameters. For example llama.cpp:
   * {
   *   mirostat_eta: 0.8,
   *   mirostat_tau: 0.9,
   *   mirostat: 1,
   *   grammar: [JSON grammar]
   * }
   */
  additionalReqBodyParams?: any
  singleFileMode?: boolean
}

export interface Stats {
  total: number
  success: number
  failed: number
}

export interface TransmartStats {
  locales?: Stats
  // TODO:
  namespaces: Stats
}

export interface TranslateParams {
  content: string
  baseLang: string
  targetLang: string
  context?: string
  retryTimes?: number
  openAIApiModel: string
  openAIApiKey: string
  openAIApiUrl: string
  openAIApiUrlPath: string
  systemPromptTemplate: TransmartOptions['systemPromptTemplate']
  additionalReqBodyParams: any
}

export interface TranslateResult {
  content?: string
  work: RunWork
  failed: boolean
  progress?: number
  total?: number
  reason?: Error
}

export interface RunOptions {
  onStart?: (work: RunWork) => any
  onProgress?: (current: number, total: number, work: RunWork) => any
  onResult: (result: TranslateResult) => any
}

export interface RunWork {
  namespace: string
  baseLocale: string
  locale: string
  inputNSFilePath: string
  outputNSFilePath: string
  cachePath: string
}


================================================
FILE: packages/core/src/util.ts
================================================
import { createHash } from 'node:crypto'
import { readFileSync } from 'node:fs'
import * as path from 'path'

/**
 * A function that returns a hash of the input data and output file paths
 * If any of the input data or output file paths change, the hash will change
 * @param inputNSFilePath
 * @param outputNSFilePath
 * @returns
 */
export const getPairHash = (inputNSFilePath: string, outputNSFilePath: string): string => {
  const data = readFileSync(inputNSFilePath, { encoding: 'utf-8' })
  const hash = createHash('sha1')
  hash.update(data)
  hash.update(path.relative(process.cwd(), outputNSFilePath))
  return hash.digest('hex')
}


================================================
FILE: packages/core/test/locales/de/common.json
================================================
{
  "create_app": "Anwendung erstellen",
  "slogan_title": "Erstellen Sie ChatGPT-Anwendungen in Sekunden",
  "site_desc": "Verwenden Sie sofort eine Vielzahl von ChatGPT-Anwendungen oder erstellen Sie Ihre eigene in Sekundenschnelle.",
  "get_started": "Loslegen",
  "icon": "Symbol",
  "pick_emoji_icon": "Wählen Sie ein Emoji als Symbol für Ihre Anwendung!",
  "app_name": "Anwendungsname",
  "app_name_placeholder": "Intelligenter Übersetzungshelfer",
  "app_desc": "Anwendungsbeschreibung",
  "app_desc_placeholder": "Diese App kann Inhalte aus jeder Sprache ins Chinesische übersetzen.",
  "prompt": "Befehl",
  "prompt_desc_placeholder": "Sie sind ein Übersetzer und müssen unabhängig vom Eingangsinhalt alles ins Chinesische übersetzen. Inhalt:",
  "prompt_desc": "Der Befehl sollte klar, leicht verständlich, logisch und ChatGPT als persönlicher Assistent dienen.",
  "prompt_example": "Beispiel für Eingabe",
  "test_before_submit": "Bitte testen Sie vor dem Einreichen",
  "cancel": "Abbrechen",
  "test": "Testen",
  "create": "Erstellen",
  "result": "Ergebnis",
  "copied_success": "Erfolgreich kopiert",
  "run": "Ausführen",
  "follow": "Folgen",
  "and": "und",
  "get_updates": ", erhalten Sie die neuesten Updates",
  "recommend": "Empfehlen",
  "developing": "Wahnsinnig in der Entwicklung",
  "app_list": "Anwendungsliste"
}

================================================
FILE: packages/core/test/locales/de/tos.json
================================================
{
  "title": "Nutzungsbedingungen für Open Assistant",
  "content": "Um Open Assistant weiterhin nutzen zu können, müssen Sie zuerst unsere Nutzungsbedingungen akzeptieren.",
  "accept": "Akzeptieren",
  "decline": "Ablehnen"
}

================================================
FILE: packages/core/test/locales/en/common.json
================================================
{
  "create_app": "Create Application",
  "slogan_title": "Create ChatGPT Application in seconds",
  "site_desc": "Instantly use a vast array of ChatGPT applications or create your own within seconds.",
  "get_started": "Get Started",
  "icon": "Icon",
  "pick_emoji_icon": "Pick an emoji as your application icon!",
  "app_name": "Application Name",
  "app_name_placeholder": "Intelligent Translation Assistant",
  "app_desc": "Application Description",
  "app_desc_placeholder": "This App can translate content from any language to Chinese.",
  "prompt": "Command",
  "prompt_desc_placeholder": "You're a translator, and no matter what the input is, you have to translate it into Chinese. Content:",
  "prompt_desc": "The command should be clear, easy to understand, logical, and let ChatGPT be your personal assistant.",
  "prompt_example": "Input Example",
  "test_before_submit": "Please test before submitting",
  "cancel": "Cancel",
  "test": "Test",
  "create": "Create",
  "result": "Result",
  "copied_success": "Copied Successfully",
  "run": "Run",
  "follow": "Follow",
  "and": "and",
  "get_updates": ", get the latest updates",
  "recommend": "Recommend",
  "developing": "Crazily Developing",
  "app_list": "Application List"
}


================================================
FILE: packages/core/test/locales/en/large-file.json
================================================
{
  "default_template_anchor": {
    "message": "Anchor",
    "description": "Title of the Anchor template."
  },
  "default_template_bbcode": {
    "message": "BBCode",
    "description": "Title of the BBCode template."
  },
  "default_template_encoded": {
    "message": "Encoded",
    "description": "Title of the Encoded template."
  },
  "default_template_markdown": {
    "message": "Markdown",
    "description": "Title of the Markdown template."
  },
  "default_template_markdown_selection": {
    "message": "Selection in Markdown",
    "description": "Title of the Selection in Markdown template."
  },
  "default_template_short": {
    "message": "Short",
    "description": "Title of the Short template."
  },
  "default_template_url": {
    "message": "URL",
    "description": "Title of the URL template."
  },
  "description": {
    "message": "Quickly and easily copies info on the current page using a simple and unique template system",
    "description": "Brief description of the extension."
  },
  "empty": {
    "message": "Empty",
    "description": "Popup/menu text where no Templates are active."
  },
  "error_file_aborted": {
    "message": "Aborted!",
    "description": "Error message for when a file upload is aborted."
  },
  "error_file_default": {
    "message": "Could not read/write file!",
    "description": "Error message for when an uploaded file couldn't be read."
  },
  "error_file_not_found": {
    "message": "File not found!",
    "description": "Error message for when a file could not be found."
  },
  "error_import_data": {
    "message": "Unable to parse data!",
    "description": "Error message for when imported data isn't valid."
  },
  "error_import_invalid": {
    "message": "Some values are missing or corrupt!",
    "description": "Error message for when imported data isn't structured correctly."
  },
  "icon_adjust": {
    "message": "Adjust",
    "description": "Adjust icon caption."
  },
  "icon_align_center": {
    "message": "Align Centre",
    "description": "Align Centre icon caption."
  },
  "icon_align_justify": {
    "message": "Align Justify",
    "description": "Align Justify icon caption."
  },
  "icon_align_left": {
    "message": "Align Left",
    "description": "Align Left icon caption."
  },
  "icon_align_right": {
    "message": "Align Right",
    "description": "Align Right icon caption."
  },
  "icon_arrow_down": {
    "message": "Arrow Down",
    "description": "Arrow Down icon caption."
  },
  "icon_arrow_left": {
    "message": "Arrow Left",
    "description": "Arrow Left icon caption."
  },
  "icon_arrow_right": {
    "message": "Arrow Right",
    "description": "Arrow Right icon caption."
  },
  "icon_arrow_up": {
    "message": "Arrow Up",
    "description": "Arrow Up icon caption."
  },
  "icon_asterisk": {
    "message": "Asterisk",
    "description": "Asterisk icon caption."
  },
  "icon_backward": {
    "message": "Backward",
    "description": "Backward icon caption."
  },
  "icon_ban_circle": {
    "message": "Ban Circle",
    "description": "Ban Circle icon caption."
  },
  "icon_barcode": {
    "message": "Barcode",
    "description": "Barcode icon caption."
  },
  "icon_bell": {
    "message": "Bell",
    "description": "Bell icon caption."
  },
  "icon_bold": {
    "message": "Bold",
    "description": "Bold icon caption."
  },
  "icon_book": {
    "message": "Book",
    "description": "Book icon caption."
  },
  "icon_bookmark": {
    "message": "Bookmark",
    "description": "Bookmark icon caption."
  },
  "icon_briefcase": {
    "message": "Briefcase",
    "description": "Briefcase icon caption."
  },
  "icon_bullhorn": {
    "message": "Bullhorn",
    "description": "Bullhorn icon caption."
  },
  "icon_calendar": {
    "message": "Calendar",
    "description": "Calendar icon caption."
  },
  "icon_camera": {
    "message": "Camera",
    "description": "Camera icon caption."
  },
  "icon_certificate": {
    "message": "Certificate",
    "description": "Certificate icon caption."
  },
  "icon_check": {
    "message": "Check",
    "description": "Check icon caption."
  },
  "icon_chevron_down": {
    "message": "Chevron Down",
    "description": "Chevron Down icon caption."
  },
  "icon_chevron_left": {
    "message": "Chevron Left",
    "description": "Chevron Left icon caption."
  },
  "icon_chevron_right": {
    "message": "Chevron Right",
    "description": "Chevron Right icon caption."
  },
  "icon_chevron_up": {
    "message": "Chevron Up",
    "description": "Chevron Up icon caption."
  },
  "icon_circle_arrow_down": {
    "message": "Circle Arrow Down",
    "description": "Circle Arrow Down icon caption."
  },
  "icon_circle_arrow_left": {
    "message": "Circle Arrow Left",
    "description": "Circle Arrow Left icon caption."
  },
  "icon_circle_arrow_right": {
    "message": "Circle Arrow Right",
    "description": "Circle Arrow Right icon caption."
  },
  "icon_circle_arrow_up": {
    "message": "Circle Arrow Up",
    "description": "Circle Arrow Up icon caption."
  },
  "icon_cog": {
    "message": "Cog",
    "description": "Cog icon caption."
  },
  "icon_comment": {
    "message": "Comment",
    "description": "Comment icon caption."
  },
  "icon_download": {
    "message": "Download",
    "description": "Download icon caption."
  },
  "icon_download_alt": {
    "message": "Download (alt)",
    "description": "Download (alt) icon caption."
  },
  "icon_edit": {
    "message": "Edit",
    "description": "Edit icon caption."
  },
  "icon_eject": {
    "message": "Eject",
    "description": "Eject icon caption."
  },
  "icon_envelope": {
    "message": "Envelope",
    "description": "Envelope icon caption."
  },
  "icon_exclamation_sign": {
    "message": "Exclamation Sign",
    "description": "Exclamation Sign icon caption."
  },
  "icon_eye_close": {
    "message": "Eye Closed",
    "description": "Eye Closed icon caption."
  },
  "icon_eye_open": {
    "message": "Eye Open",
    "description": "Eye Open icon caption."
  },
  "icon_facetime_video": {
    "message": "Facetime Video",
    "description": "Facetime Video icon caption."
  },
  "icon_fast_backward": {
    "message": "Fast Backward",
    "description": "Fast Backward icon caption."
  },
  "icon_fast_forward": {
    "message": "Fast Forward",
    "description": "Fast Forward icon caption."
  },
  "icon_file": {
    "message": "File",
    "description": "File icon caption."
  },
  "icon_film": {
    "message": "Film",
    "description": "Film icon caption."
  },
  "icon_filter": {
    "message": "Filter",
    "description": "Filter icon caption."
  },
  "icon_fire": {
    "message": "Fire",
    "description": "Fire icon caption."
  },
  "icon_flag": {
    "message": "Flag",
    "description": "Flag icon caption."
  },
  "icon_folder_close": {
    "message": "Folder Closed",
    "description": "Folder Closed icon caption."
  },
  "icon_folder_open": {
    "message": "Folder Open",
    "description": "Folder Open icon caption."
  },
  "icon_font": {
    "message": "Font",
    "description": "Font icon caption."
  },
  "icon_forward": {
    "message": "Forward",
    "description": "Forward icon caption."
  },
  "icon_fullscreen": {
    "message": "Fullscreen",
    "description": "Fullscreen icon caption."
  },
  "icon_gift": {
    "message": "Gift",
    "description": "Gift icon caption."
  },
  "icon_glass": {
    "message": "Glass",
    "description": "Glass icon caption."
  },
  "icon_globe": {
    "message": "Globe",
    "description": "Globe icon caption."
  },
  "icon_hand_down": {
    "message": "Hand Down",
    "description": "Hand Down icon caption."
  },
  "icon_hand_left": {
    "message": "Hand Left",
    "description": "Hand Left icon caption."
  },
  "icon_hand_right": {
    "message": "Hand Right",
    "description": "Hand Right icon caption."
  },
  "icon_hand_up": {
    "message": "Hand Up",
    "description": "Hand Up icon caption."
  },
  "icon_hdd": {
    "message": "HDD",
    "description": "HDD icon caption."
  },
  "icon_headphones": {
    "message": "Headphones",
    "description": "Headphones icon caption."
  },
  "icon_heart": {
    "message": "Heart",
    "description": "Heart icon caption."
  },
  "icon_home": {
    "message": "Home",
    "description": "Home icon caption."
  },
  "icon_inbox": {
    "message": "Inbox",
    "description": "Inbox icon caption."
  },
  "icon_indent_left": {
    "message": "Indent Left",
    "description": "Indent Left icon caption."
  },
  "icon_indent_right": {
    "message": "Indent Right",
    "description": "Indent Right icon caption."
  },
  "icon_info_sign": {
    "message": "Info Sign",
    "description": "Info Sign icon caption."
  },
  "icon_italic": {
    "message": "Italic",
    "description": "Italic icon caption."
  },
  "icon_leaf": {
    "message": "Leaf",
    "description": "Leaf icon caption."
  },
  "icon_list": {
    "message": "List",
    "description": "List icon caption."
  },
  "icon_list_alt": {
    "message": "List (alt)",
    "description": "List (alt) icon caption."
  },
  "icon_lock": {
    "message": "Lock",
    "description": "Lock icon caption."
  },
  "icon_magnet": {
    "message": "Magnet",
    "description": "Magnet icon caption."
  },
  "icon_map_marker": {
    "message": "Map Marker",
    "description": "Map Marker icon caption."
  },
  "icon_minus": {
    "message": "Minus",
    "description": "Minus icon caption."
  },
  "icon_minus_sign": {
    "message": "Minus Sign",
    "description": "Minus Sign icon caption."
  },
  "icon_move": {
    "message": "Move",
    "description": "Move icon caption."
  },
  "icon_music": {
    "message": "Music",
    "description": "Music icon caption."
  },
  "icon_none": {
    "message": "None",
    "description": "None icon caption."
  },
  "icon_off": {
    "message": "Off",
    "description": "Off icon caption."
  },
  "icon_ok": {
    "message": "OK",
    "description": "OK icon caption."
  },
  "icon_ok_circle": {
    "message": "OK Circle",
    "description": "OK Circle icon caption."
  },
  "icon_ok_sign": {
    "message": "OK Sign",
    "description": "OK Sign icon caption."
  },
  "icon_pause": {
    "message": "Pause",
    "description": "Pause icon caption."
  },
  "icon_pencil": {
    "message": "Pencil",
    "description": "Pencil icon caption."
  },
  "icon_picture": {
    "message": "Picture",
    "description": "Picture icon caption."
  },
  "icon_plane": {
    "message": "Plane",
    "description": "Plane icon caption."
  },
  "icon_play": {
    "message": "Play",
    "description": "Play icon caption."
  },
  "icon_play_circle": {
    "message": "Play Circle",
    "description": "Play Circle icon caption."
  },
  "icon_plus": {
    "message": "Plus",
    "description": "Plus icon caption."
  },
  "icon_plus_sign": {
    "message": "Plus Sign",
    "description": "Plus Sign icon caption."
  },
  "icon_print": {
    "message": "Print",
    "description": "Print icon caption."
  },
  "icon_qrcode": {
    "message": "QR Code",
    "description": "QR Code icon caption."
  },
  "icon_question_sign": {
    "message": "Question Sign",
    "description": "Question Sign icon caption."
  },
  "icon_random": {
    "message": "Random",
    "description": "Random icon caption."
  },
  "icon_refresh": {
    "message": "Refresh",
    "description": "Refresh icon caption."
  },
  "icon_remove": {
    "message": "Remove",
    "description": "Remove icon caption."
  },
  "icon_remove_circle": {
    "message": "Remove Circle",
    "description": "Remove Circle icon caption."
  },
  "icon_remove_sign": {
    "message": "Remove Sign",
    "description": "Remove Sign icon caption."
  },
  "icon_repeat": {
    "message": "Repeat",
    "description": "Repeat icon caption."
  },
  "icon_resize_full": {
    "message": "Resize Full",
    "description": "Resize Full icon caption."
  },
  "icon_resize_horizontal": {
    "message": "Resize Horizontal",
    "description": "Resize Horizontal icon caption."
  },
  "icon_resize_small": {
    "message": "Resize Small",
    "description": "Resize Small icon caption."
  },
  "icon_resize_vertical": {
    "message": "Resize Vertical",
    "description": "Resize Vertical icon caption."
  },
  "icon_retweet": {
    "message": "Retweet",
    "description": "Retweet icon caption."
  },
  "icon_road": {
    "message": "Road",
    "description": "Road icon caption."
  },
  "icon_screenshot": {
    "message": "Screenshot",
    "description": "Screenshot icon caption."
  },
  "icon_search": {
    "message": "Search",
    "description": "Search icon caption."
  },
  "icon_share": {
    "message": "Share",
    "description": "Share icon caption."
  },
  "icon_share_alt": {
    "message": "Share (alt)",
    "description": "Share (alt) icon caption."
  },
  "icon_shopping_cart": {
    "message": "Shopping Cart",
    "description": "Shopping Cart icon caption."
  },
  "icon_signal": {
    "message": "Signal",
    "description": "Signal icon caption."
  },
  "icon_star": {
    "message": "Star",
    "description": "Star icon caption."
  },
  "icon_star_empty": {
    "message": "Star Empty",
    "description": "Star Empty icon caption."
  },
  "icon_step_backward": {
    "message": "Step Backward",
    "description": "Step Backward icon caption."
  },
  "icon_step_forward": {
    "message": "Step Forward",
    "description": "Step Forward icon caption."
  },
  "icon_stop": {
    "message": "Stop",
    "description": "Stop icon caption."
  },
  "icon_tag": {
    "message": "Tag",
    "description": "Tag icon caption."
  },
  "icon_tags": {
    "message": "Tags",
    "description": "Tags icon caption."
  },
  "icon_tasks": {
    "message": "Tasks",
    "description": "Tasks icon caption."
  },
  "icon_text_height": {
    "message": "Text Height",
    "description": "Text Height icon caption."
  },
  "icon_text_width": {
    "message": "Text Width",
    "description": "Text Width icon caption."
  },
  "icon_th": {
    "message": "Thumbnails",
    "description": "Thumbnails icon caption."
  },
  "icon_th_large": {
    "message": "Thumbnails Large",
    "description": "Thumbnails Large icon caption."
  },
  "icon_th_list": {
    "message": "Thumbnails List",
    "description": "Thumbnails List icon caption."
  },
  "icon_thumbs_down": {
    "message": "Thumbs Down",
    "description": "Thumbs Down icon caption."
  },
  "icon_thumbs_up": {
    "message": "Thumbs Up",
    "description": "Thumbs Up icon caption."
  },
  "icon_time": {
    "message": "Time",
    "description": "Time icon caption."
  },
  "icon_tint": {
    "message": "Tint",
    "description": "Tint icon caption."
  },
  "icon_trash": {
    "message": "Trash",
    "description": "Trash icon caption."
  },
  "icon_upload": {
    "message": "Upload",
    "description": "Upload icon caption."
  },
  "icon_user": {
    "message": "User",
    "description": "User icon caption."
  },
  "icon_volume_down": {
    "message": "Volume Down",
    "description": "Volume Down icon caption."
  },
  "icon_volume_off": {
    "message": "Volume Off",
    "description": "Volume Off icon caption."
  },
  "icon_volume_up": {
    "message": "Volume Up",
    "description": "Volume Up icon caption."
  },
  "icon_warning_sign": {
    "message": "Warning Sign",
    "description": "Warning Sign icon caption."
  },
  "icon_wrench": {
    "message": "Wrench",
    "description": "Wrench icon caption."
  },
  "icon_zoom_in": {
    "message": "Zoom In",
    "description": "Zoom In icon caption."
  },
  "icon_zoom_out": {
    "message": "Zoom Out",
    "description": "Zoom Out icon caption."
  },
  "name": {
    "message": "Template",
    "description": "Name of the extension."
  },
  "opt_add_button_text": {
    "message": "$ICON$ Add",
    "description": "Text of button used to add templates.",
    "placeholders": {
      "icon": {
        "content": "<i class=\"icon-plus icon-white\"></i>",
        "example": "<i class=\"icon-plus icon-white\"></i>"
      }
    }
  },
  "opt_add_button_title": {
    "message": "Create a new template",
    "description": "Hover text of button used to add templates."
  },
  "opt_analytics_label": {
    "message": "Analytics",
    "description": "Label for the Analytics field."
  },
  "opt_analytics_sub_text": {
    "message": "This information is only ever used to help improve user experience and will never be supplied to a 3rd party",
    "description": "Help text for the Analytics field."
  },
  "opt_analytics_text": {
    "message": "Send anonymous usage statistics",
    "description": "Text for the Analytics field."
  },
  "opt_confirm_button": {
    "message": "Confirm",
    "description": "Text for a Confirm button."
  },
  "opt_delete_button_text": {
    "message": "$ICON$ Delete",
    "description": "Text for the Delete button.",
    "placeholders": {
      "icon": {
        "content": "<i class=\"icon-trash icon-white\"></i>",
        "example": "<i class=\"icon-trash icon-white\"></i>"
      }
    }
  },
  "opt_delete_button_title": {
    "message": "Delete all selected templates",
    "description": "Hover text for the Delete button."
  },
  "opt_delete_wizard_header": {
    "message": "Confirm Deletion",
    "description": "Header for the confirmation dialog displayed when deleting template(s)."
  },
  "opt_delete_wizard_text_1": {
    "message": "This action is $O_BOLD$permanent$C_BOLD$ and cannot be reversed. The following template(s) will be removed;",
    "description": "1st paragraph for the confirmation dialog displayed when deleting a template.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_delete_wizard_text_2": {
    "message": "Do you want to continue anyway?",
    "description": "2nd paragraph for the confirmation dialog displayed when deleting a template."
  },
  "opt_disable_button_text": {
    "message": "$ICON$ Disable",
    "description": "Text of button used to disable templates.",
    "placeholders": {
      "icon": {
        "content": "<i class=\"icon-remove\"></i>",
        "example": "<i class=\"icon-remove\"></i>"
      }
    }
  },
  "opt_disable_button_title": {
    "message": "Disable all selected templates",
    "description": "Hover text of button used to disable templates."
  },
  "opt_donate_button": {
    "message": "$ICON$ Donate",
    "description": "Text for the Donate button.",
    "placeholders": {
      "icon": {
        "content": "<i class=\"icon-heart icon-white\"></i>",
        "example": "<i class=\"icon-heart icon-white\"></i>"
      }
    }
  },
  "opt_donate_button_title": {
    "message": "Share the love!",
    "description": "Hover text for the Donate button."
  },
  "opt_enable_button_text": {
    "message": "$ICON$ Enable",
    "description": "Text of button used to enable templates.",
    "placeholders": {
      "icon": {
        "content": "<i class=\"icon-ok\"></i>",
        "example": "<i class=\"icon-ok\"></i>"
      }
    }
  },
  "opt_enable_button_title": {
    "message": "Enable all selected templates",
    "description": "Hover text of button used to enable templates."
  },
  "opt_errors_header": {
    "message": "The following problem(s) need to be corrected;",
    "description": "Preceding text for any errors on the Templates tab."
  },
  "opt_export_button_text": {
    "message": "$ICON$ Export",
    "description": "Text for the Export button.",
    "placeholders": {
      "icon": {
        "content": "<i class=\"icon-upload\"></i>",
        "example": "<i class=\"icon-upload\"></i>"
      }
    }
  },
  "opt_export_button_title": {
    "message": "Export all selected templates",
    "description": "Hover text for the Export button."
  },
  "opt_export_wizard_copy_alt_button": {
    "message": "Copied!",
    "description": "Text for the Copy button, used for a short duration after being clicked."
  },
  "opt_export_wizard_copy_button": {
    "message": "Copy",
    "description": "Text for the Copy button."
  },
  "opt_export_wizard_header": {
    "message": "Export",
    "description": "Header for the Export dialog."
  },
  "opt_export_wizard_save_as_button": {
    "message": "Save As...",
    "description": "Text for the Save As... button."
  },
  "opt_export_wizard_text": {
    "message": "Copy or download the exported template data.",
    "description": "Text for the Export dialog."
  },
  "opt_feedback_button": {
    "message": "feedback",
    "description": "Text of Feedback button on the Options page."
  },
  "opt_general_header": {
    "message": "General",
    "description": "Header of the General tab."
  },
  "opt_guide_argument_header": {
    "message": "Argument",
    "description": "Header for the Argument column."
  },
  "opt_guide_argument_number_text": {
    "message": "Number",
    "description": "Text for operations that take numeric arguments, displayed in the Argument column."
  },
  "opt_guide_argument_text_text": {
    "message": "Text",
    "description": "Text for operations that take string arguments, displayed in the Argument column."
  },
  "opt_guide_definitions_caption": {
    "message": "Definitions",
    "description": "Caption displayed above all Definitions tables."
  },
  "opt_guide_definitions_footer_1": {
    "message": "Not available on internal Chrome pages or the $O_LINK_WEBSTORE$Chrome Web Store$C_LINK$",
    "description": "First optional footer displayed below Definitions tables.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_webstore": {
        "content": "<a href=\"https://chrome.google.com/webstore\" target=\"_blank\">",
        "example": "<a href=\"https://chrome.google.com/webstore\">"
      }
    }
  },
  "opt_guide_definitions_footer_2": {
    "message": "Only available when Template is accessed via the context menu of a link",
    "description": "Second optional footer displayed below Definitions tables."
  },
  "opt_guide_definitions_footer_3": {
    "message": "Learn more about the $O_LINK_SELECTORS$Selectors API$C_LINK$",
    "description": "Third optional footer displayed below Definitions tables.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_selectors": {
        "content": "<a href=\"http://www.w3.org/TR/selectors-api/\" target=\"_blank\">",
        "example": "<a href=\"http://www.w3.org/TR/selectors-api/\">"
      }
    }
  },
  "opt_guide_definitions_footer_4": {
    "message": "Learn more about the $O_LINK_XPATH$XPath API$C_LINK$",
    "description": "Fourth optional footer displayed below Definitions tables.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_xpath": {
        "content": "<a href=\"http://www.w3.org/TR/xpath/\" target=\"_blank\">",
        "example": "<a href=\"http://www.w3.org/TR/xpath/\">"
      }
    }
  },
  "opt_guide_description_header": {
    "message": "Description",
    "description": "Header for the Description column."
  },
  "opt_guide_examples_header": {
    "message": "Examples",
    "description": "Header for all expandable Examples areas."
  },
  "opt_guide_header": {
    "message": "Guide",
    "description": "Header for the Guide tab."
  },
  "opt_guide_introduction_case_sensitivity_header": {
    "message": "Case Sensitivity",
    "description": "Header for the Case Sensitivity area on the Guide tab of the Options page under the Introduction section."
  },
  "opt_guide_introduction_case_sensitivity_text": {
    "message": "The names of simple tags and sections are case-insensitive, therefore $SYNTAX_1$ will output the same as $SYNTAX_2$. However, sections must be opened and closed with names in the same case (i.e. $SYNTAX_3$ will not work).",
    "description": "Text for the Case Sensitivity area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "syntax_1": {
        "content": "<code>{name}</code>",
        "example": "{name}"
      },
      "syntax_2": {
        "content": "<code>{NaMe}</code>",
        "example": "{NaMe}"
      },
      "syntax_3": {
        "content": "<code>{#name}...{/NaMe}</code>",
        "example": "{#name}...{/NaMe}"
      }
    }
  },
  "opt_guide_introduction_dot_notation_header": {
    "message": "Dot Notation",
    "description": "Header for the Dot Notation area on the Guide tab of the Options page under the Introduction section."
  },
  "opt_guide_introduction_dot_notation_text": {
    "message": "Nested properties of objects can also be accessed using dot notation like $SYNTAX$ which would get the $O_EMPH$nested$C_EMPH$ property of the $O_EMPH$name$C_EMPH$ object. These expressions can be even chained to access properties of nested properties and so on.",
    "description": "Text for the Dot Notation area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      },
      "syntax": {
        "content": "<code>{name.nested}</code>",
        "example": "{name.nested}"
      }
    }
  },
  "opt_guide_introduction_header": {
    "message": "Introduction",
    "description": "Header for the Introductions section on the Guide tab of the Options page."
  },
  "opt_guide_introduction_inverted_section_access_text": {
    "message": "$O_BOLD$Access$C_BOLD$ - Only renders the contents if the value is an empty object",
    "description": "Text for the Access item in the list within the Inverted Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_introduction_inverted_section_conditions_text": {
    "message": "$O_BOLD$Conditions$C_BOLD$ - Only renders the contents if the value is $O_EMPH$falsey$C_EMPH$",
    "description": "Text for the Conditions item in the list within the Inverted Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      }
    }
  },
  "opt_guide_introduction_inverted_section_header": {
    "message": "Inverted Section",
    "description": "Header for the Inverted Section area on the Guide tab of the Options page under the Introduction section."
  },
  "opt_guide_introduction_inverted_section_iterating_text": {
    "message": "$O_BOLD$Iterating$C_BOLD$ - Only renders the contents if the value is an empty list",
    "description": "Text for the Iterating item in the list within the Inverted Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_introduction_inverted_section_text": {
    "message": "Inverted sections are very similar to normal sections but are written like this $SYNTAX$ and can be used in for the following purposes;",
    "description": "Text for the Inverted Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "syntax": {
        "content": "<code>{^name}...{/name}</code>",
        "example": "{^name}...{/name}"
      }
    }
  },
  "opt_guide_introduction_notes_text_1": {
    "message": "If you are having problems with understanding this guide please $O_LINK_HELP_DESK$let us know$C_LINK$ and we will try to help you and take your comments on board, updating the documentation if required.",
    "description": "1st paragraph for the Notes area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_help_desk": {
        "content": "<a href=\"http://template.uservoice.com/\" target=\"_blank\">",
        "example": "<a href=\"http://template.uservoice.com/\">"
      }
    }
  },
  "opt_guide_introduction_notes_text_2": {
    "message": "If you encounter any problems while using $O_BOLD$Template$C_BOLD$ and/or would like to see a change or addition, please $O_LINK_HELP_DESK$raise a ticket$C_LINK$ and we will have a look at it.",
    "description": "2nd paragraph for the Notes area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      },
      "o_link_help_desk": {
        "content": "<a href=\"http://template.uservoice.com/\" target=\"_blank\">",
        "example": "<a href=\"http://template.uservoice.com/\">"
      }
    }
  },
  "opt_guide_introduction_notes_text_3": {
    "message": "For more examples, try looking at the predefined templates.",
    "description": "3rd paragraph for the Notes area on the Guide tab of the Options page under the Introduction section."
  },
  "opt_guide_introduction_section_access_text": {
    "message": "$O_BOLD$Access$C_BOLD$ - If the value is an object it will render the contents while exposing the properties of that object as variables",
    "description": "Text for the Access item in the list within the Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_introduction_section_conditions_text": {
    "message": "$O_BOLD$Conditions$C_BOLD$ - Only renders the contents if the value is $O_EMPH$truey$C_EMPH$",
    "description": "Text for the Conditions item in the list within the Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      }
    }
  },
  "opt_guide_introduction_section_header": {
    "message": "Section",
    "description": "Header for the Section area on the Guide tab of the Options page under the Introduction section."
  },
  "opt_guide_introduction_section_iterating_text": {
    "message": "$O_BOLD$Iterating$C_BOLD$ - If the value is an array it will render the contents for each enumerable item of that value",
    "description": "Text for the Iteration item in the list within the Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_introduction_section_operations_text": {
    "message": "$O_BOLD$Operations$C_BOLD$ - Renders the outcome of the operation, passing the contents as the argument",
    "description": "Text for the Operations item in the list within the Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_introduction_section_text": {
    "message": "Sections are always surrounded by opening and closing tags like this $SYNTAX$ and can be used for the following purposes;",
    "description": "Text for the Section area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "syntax": {
        "content": "<code>{#name}...{/name}</code>",
        "example": "{#name}...{/name}"
      }
    }
  },
  "opt_guide_introduction_simple_tag_header": {
    "message": "Simple Tag",
    "description": "Header for the Simple Tag area on the Guide tab of the Options page under the Introduction section."
  },
  "opt_guide_introduction_simple_tag_text_1": {
    "message": "Tags are always surrounded by curly braces like this $SYNTAX$ and output the value of the named variable. If that value is undefined or $O_EMPH$falsey$C_EMPH$ it will simply be deleted.",
    "description": "1st paragraph for the Simple Tag area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      },
      "syntax": {
        "content": "<code>{name}</code>",
        "example": "{name}"
      }
    }
  },
  "opt_guide_introduction_simple_tag_text_2": {
    "message": "Values are not escaped by default and, in order to do so, you must either use double braces like $SYNTAX_DOUBLE$ or a leading ampersand like $SYNTAX_AMP$. This will escape $CHARACTERS$ characters so that the final output can be safely copied in to $O_ABBR_1$Extensible Markup Language$O_ABBR_2$XML$C_ABBR$ and $O_ABBR_1$Hyper Text Markup Language$O_ABBR_2$HTML$C_ABBR$.",
    "description": "2nd paragraph for the Simple Tag area on the Guide tab of the Options page under the Introduction section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "characters": {
        "content": "<code>&amp;</code> <code>&lt;</code> <code>&gt;</code> <code>&quot;</code> <code>&#39;</code>",
        "example": "& < > \" '"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "syntax_amp": {
        "content": "<code>{&amp;name}</code>",
        "example": "{&name}"
      },
      "syntax_double": {
        "content": "<code>{{name}}</code>",
        "example": "{{name}}"
      }
    }
  },
  "opt_guide_introduction_text": {
    "message": "$O_BOLD$Template$C_BOLD$ uses an advanced, yet simple, template system to allows you to create and modify the content to be copied to the clipboard. The syntax is really straight-forward and consists of the following categories;",
    "description": "Header for the Introductions section on the Guide tab of the Options page.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_lists_objects_cookies_text": {
    "message": "The names of all cookies associated with the page",
    "description": "Description of the cookies variable on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_coords_text": {
    "message": "The properties of your current physical location (e.g. $EXAMPLE_1$, $EXAMPLE_2$ and many more)",
    "description": "Description of the coords variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "example_1": {
        "content": "<em>latitude</em>",
        "example": "latitude"
      },
      "example_2": {
        "content": "<em>longitude</em>",
        "example": "longitude"
      }
    }
  },
  "opt_guide_lists_objects_examples_code_1": {
    "message": "$URL$",
    "description": "Text for the 1st code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "url": {
        "content": "http://example.com/test/index.html?foo=bar&amp;fu=baz",
        "example": "http://example.com/test/index.html?foo=bar&fu=baz"
      }
    }
  },
  "opt_guide_lists_objects_examples_code_2": {
    "message": "Follow the breadcrumbs;\n$SYNTAX$",
    "description": "Text for the 2nd code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "syntax": {
        "content": "{#segments}\n * {.}\n{/segments}",
        "example": "{#segments}\n * {.}\n{/segments}"
      }
    }
  },
  "opt_guide_lists_objects_examples_code_3": {
    "message": "Follow the breadcrumbs;\n$LIST$",
    "description": "Text for the 3rd code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "list": {
        "content": " * test\n * index.html",
        "example": " * test\n * index.html"
      }
    }
  },
  "opt_guide_lists_objects_examples_code_4": {
    "message": "$SYNTAX_1$$PARAM_1$ is &quot;{$PARAM_1$}&quot; and $PARAM_2$ is &quot;{$PARAM_2$}&quot;.$SYNTAX_3$\n$SYNTAX_2$No parameters could be found!$SYNTAX_3$",
    "description": "Text for the 4th code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "param_1": {
        "content": "foo",
        "example": "foo"
      },
      "param_2": {
        "content": "fu",
        "example": "fu"
      },
      "syntax_1": {
        "content": "{#params}",
        "example": "{#params}"
      },
      "syntax_2": {
        "content": "{^params}",
        "example": "{^params}"
      },
      "syntax_3": {
        "content": "{/params}",
        "example": "{/params}"
      }
    }
  },
  "opt_guide_lists_objects_examples_code_5": {
    "message": "$PARAM_1$ is &quot;$VALUE_1$&quot; and $PARAM_2$ is &quot;$VALUE_2$&quot;.",
    "description": "Text for the 5th code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "param_1": {
        "content": "foo",
        "example": "foo"
      },
      "param_2": {
        "content": "fu",
        "example": "fu"
      },
      "value_1": {
        "content": "bar",
        "example": "bar"
      },
      "value_2": {
        "content": "baz",
        "example": "baz"
      }
    }
  },
  "opt_guide_lists_objects_examples_code_6": {
    "message": "$PARAM_1$ is &quot;{$SYNTAX$$PARAM_1$}&quot; and $PARAM_2$ is &quot;{$SYNTAX$$PARAM_2$}&quot;.",
    "description": "Text for the 6th code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "param_1": {
        "content": "foo",
        "example": "foo"
      },
      "param_2": {
        "content": "fu",
        "example": "fu"
      },
      "syntax": {
        "content": "params.",
        "example": "params."
      }
    }
  },
  "opt_guide_lists_objects_examples_code_7": {
    "message": "No parameters could be found!",
    "description": "Text for the 7th code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_code_8": {
    "message": "The site has following information stored;\n$SYNTAX$",
    "description": "Text for the 8th code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "syntax": {
        "content": "{#cookies}\n * {.} = &quot;{#cookie}{.}{/cookie}&quot;\n{/cookies}",
        "example": "{#cookies}\n * {.} = \"{#cookie}{.}{/cookie}\"\n{/cookies}"
      }
    }
  },
  "opt_guide_lists_objects_examples_code_9": {
    "message": "The site has following information stored;\n$LIST$",
    "description": "Text for the 9th code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "list": {
        "content": " * JSESSIONID = &quot;2pkffy9ivmpfwntf12y6o4cgu&quot;\n * __utmc = &quot;224978569&quot;",
        "example": " * JSESSIONID = \"2pkffy9ivmpfwntf12y6o4cgu\"\n * __utmc = \"224978569\""
      }
    }
  },
  "opt_guide_lists_objects_examples_code_10": {
    "message": "$SYNTAX_1$View Larger Map$SYNTAX_2$",
    "description": "Text for the 10th code block in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "syntax_1": {
        "content": "{#coords}\n&lt;iframe width=&quot;425&quot; height=&quot;350&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; src=&quot;http://maps.google.com/maps?ll={latitude},{longitude}&amp;output=embed&quot;&gt;&lt;/iframe&gt;\n&lt;br&gt;\n&lt;small&gt;&lt;a href=&quot;http://maps.google.com/maps?ll={latitude},{longitude}&amp;source=embed&quot;&gt;",
        "example": "{#coords}\n<iframe width=\"425\" height=\"350\" frameborder=\"0\" scrolling=\"no\" marginheight=\"0\" marginwidth=\"0\" src=\"http://maps.google.com/maps?ll={latitude},{longitude}&output=embed\"></iframe>\n<br>\n<small><a href=\"http://maps.google.com/maps?ll={latitude},{longitude}&source=embed\">"
      },
      "syntax_2": {
        "content": "&lt;/a&gt;&lt;/small&gt;\n{/coords}",
        "example": "</a></small>\n{/coords}"
      }
    }
  },
  "opt_guide_lists_objects_examples_text_1": {
    "message": "These examples will be using the following $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$;",
    "description": "Text for the 1st paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_examples_text_2": {
    "message": "As it's a list, you can do the following to iterate over all the $SEGMENTS_LABEL$;",
    "description": "Text for the 2nd paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "segments_label": {
        "content": "<span class=\"label\">segments</span>",
        "example": "segments"
      }
    }
  },
  "opt_guide_lists_objects_examples_text_3": {
    "message": "Would output the following;",
    "description": "Text for the 3rd paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_text_4": {
    "message": "In order to access the properties of an object it couldn't be any easier than this;",
    "description": "Text for the 4th paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_text_5": {
    "message": "This would output the following;",
    "description": "Text for the 5th paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_text_6": {
    "message": "Alternatively, this could be achieved using dot notation as follows;",
    "description": "Text for the 6th paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_text_7": {
    "message": "However, if the query string was empty it would output this instead;",
    "description": "Text for the 7th paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_text_8": {
    "message": "Using the following you can access the name and values of all available cookies;",
    "description": "Text for the 8th paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_text_9": {
    "message": "This will output in something like the following;",
    "description": "Text for the 9th paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_examples_text_10": {
    "message": "If you would like to embed a map of your current location (e.g. in a blog post) try the following snippet;",
    "description": "Text for the 10th paragraph in the Examples area on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_fparams_text": {
    "message": "The key/value pairs of all parameters within the hash fragment (e.g. fragment $EXAMPLE_1$ contains $EXAMPLE_2$ and $EXAMPLE_3$)",
    "description": "Description of the fparams variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "example_1": {
        "content": "<code>foo=bar&amp;fu=baz</code>",
        "example": "foo=bar&fu=baz"
      },
      "example_2": {
        "content": "<em>foo</em>",
        "example": "foo"
      },
      "example_3": {
        "content": "<em>fu</em>",
        "example": "fu"
      }
    }
  },
  "opt_guide_lists_objects_fsegments_text": {
    "message": "The segments from the hash fragment's path",
    "description": "Description of the fsegments variable on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_header": {
    "message": "Lists &amp; Objects",
    "description": "Header for the Lists & Objects section on the Guide tab of the Options page."
  },
  "opt_guide_lists_objects_images_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$s of all images on the page",
    "description": "Description of the images variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_keywords_text": {
    "message": "The keywords from the page's meta information",
    "description": "Description of the keywords variable on the Guide tab of the Options page under the Lists & Objects section."
  },
  "opt_guide_lists_objects_links_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$s of all links on the page",
    "description": "Description of the links variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_local_storage_text": {
    "message": "The items stored in the $LOCAL_STORAGE$ of the page",
    "description": "Description of the localStorage variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "local_storage": {
        "content": "<code>localStorage</code>",
        "example": "localStorage"
      }
    }
  },
  "opt_guide_lists_objects_params_text": {
    "message": "The key/value pairs of all parameters (e.g. query $EXAMPLE_1$ contains $EXAMPLE_2$ and $EXAMPLE_3$)",
    "description": "Description of the params variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "example_1": {
        "content": "<code>foo=bar&amp;fu=baz</code>",
        "example": "foo=bar&fu=baz"
      },
      "example_2": {
        "content": "<em>foo</em>",
        "example": "foo"
      },
      "example_3": {
        "content": "<em>fu</em>",
        "example": "fu"
      }
    }
  },
  "opt_guide_lists_objects_plugins_text": {
    "message": "The names of all enabled browser plugins (e.g. $EXAMPLE$)",
    "description": "Description of the plugins variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "example": {
        "content": "<em>Shockwave Flash</em>",
        "example": "Shockwave Flash"
      }
    }
  },
  "opt_guide_lists_objects_popular_text": {
    "message": "The properties of your most popular template (e.g. $EXAMPLE_1$, $EXAMPLE_2$, $EXAMPLE_3$ and many more)",
    "description": "Description of the popular variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "example_1": {
        "content": "<em>title</em>",
        "example": "title"
      },
      "example_2": {
        "content": "<em>content</em>",
        "example": "content"
      },
      "example_3": {
        "content": "<em>shortcut</em>",
        "example": "shortcut"
      }
    }
  },
  "opt_guide_lists_objects_scripts_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$s of all external script used by the page",
    "description": "Description of the scripts variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_segments_text": {
    "message": "The segments from the $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$'s path",
    "description": "Description of the segments variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_selected_images_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$s of all images within the current selection",
    "description": "Description of the selectedImages variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_selected_links_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$s of all links within the current selection",
    "description": "Description of the selectedLinks variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_session_storage_text": {
    "message": "The items stored in the $SESSION_STORAGE$ of the page",
    "description": "Description of the sessionStorage variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "session_storage": {
        "content": "<code>sessionStorage</code>",
        "example": "sessionStorage"
      }
    }
  },
  "opt_guide_lists_objects_style_sheets_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$s of all external $O_ABBR_1$Cascading Style Sheets$O_ABBR_2$CSS$C_ABBR$ resources used by the page",
    "description": "Description of the styleSheets variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_tabs_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$s of all tabs open in the current window",
    "description": "Description of the tabs variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_lists_objects_template_text": {
    "message": "The properties of the activated template (e.g. $EXAMPLE_1$, $EXAMPLE_2$, $EXAMPLE_3$ and many more)",
    "description": "Description of the template variable on the Guide tab of the Options page under the Lists & Objects section.",
    "placeholders": {
      "example_1": {
        "content": "<em>title</em>",
        "example": "title"
      },
      "example_2": {
        "content": "<em>image</em>",
        "example": "image"
      },
      "example_3": {
        "content": "<em>usage</em>",
        "example": "usage"
      }
    }
  },
  "opt_guide_lists_objects_text": {
    "message": "$O_BOLD$Lists &amp; Objects$C_BOLD$ are generally accessed using sections (including inverted) to iterate over and access properties respectively. However, simple tags can be used to output the contents of a list or the properties of an object in $O_ABBR_1$Comma-Separated Values$O_ABBR_2$CSV$C_ABBR$ format.",
    "description": "Text for the Lists & Objects section on the Guide tab of the Options page.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_name_header": {
    "message": "Name",
    "description": "Header for the Name column on the Guide tab of the Options page under all of the specific sections."
  },
  "opt_guide_new_text": {
    "message": "New",
    "description": "Label for new variables on the Guide tab of the Options page under all of the specific sections."
  },
  "opt_guide_notes_header": {
    "message": "Notes",
    "description": "Header for the Notes area on the Guide tab of the Options page under some sections."
  },
  "opt_guide_operations_capitalise_name": {
    "message": "capitalise",
    "description": "Name of the capitalise variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_capitalise_text": {
    "message": "Transform the text provided into title case",
    "description": "Description of the capitalise variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_cookie_text": {
    "message": "Get the value for the cookie with the name provided",
    "description": "Description of the cookie variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_date_time_text_1": {
    "message": "Format the current date &amp; time using the pattern provided",
    "description": "1st line of the description of the dateTime variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_date_time_text_2": {
    "message": "(see $O_LINK_PHP_DATE$$O_ABBR_1$Hypertext Preprocessor$O_ABBR_2$PHP$C_ABBR$s date$C_LINK$ for more details)",
    "description": "2nd line of the description of the dateTime variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_php_date": {
        "content": "<a href=\"http://php.net/manual/en/function.date.php#refsect1-function.date-parameters\" target=\"_blank\">",
        "example": "<a href=\"http://php.net/manual/en/function.date.php#refsect1-function.date-parameters\">"
      }
    }
  },
  "opt_guide_operations_decode_text": {
    "message": "Decode the previously encoded text provided",
    "description": "Description of the decode variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_encode_text": {
    "message": "Encode the text provided so that it can be safely used in a query string",
    "description": "Description of the encode variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_escape_text": {
    "message": "Escape the text provided so that it can be safely inserted into $O_ABBR_1$HyperText Markup Language$O_ABBR_2$HTML$C_ABBR$",
    "description": "Description of the escape variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_operations_examples_code_1": {
    "message": "$URL$",
    "description": "Text for the 1st code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "url": {
        "content": "http://example.com/test/index.html?foo=bar&amp;fu=baz",
        "example": "http://example.com/test/index.html?foo=bar&fu=baz"
      }
    }
  },
  "opt_guide_operations_examples_code_2": {
    "message": "Today is $SYNTAX$.",
    "description": "Text for the 2nd code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "syntax": {
        "content": "{#dateTime}Y-m-d\\TH:i:sP{/dateTime}",
        "example": "{#dateTime}Y-m-d\\TH:i:sP{/dateTime}"
      }
    }
  },
  "opt_guide_operations_examples_code_3": {
    "message": "$URL$",
    "description": "Text for the 3rd code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "url": {
        "content": "http://example.com/something.do?url={#encode}{url}{/encode}",
        "example": "http://example.com/something.do?url={#encode}{url}{/encode}"
      }
    }
  },
  "opt_guide_operations_examples_code_4": {
    "message": "$URL$",
    "description": "Text for the 4th code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "url": {
        "content": "http://example.com/something.do?url=http%3A%2F%2Fexample.com%2Ftest%2Findex.html%3Ffoo%3Dbar%26fu%3Dbaz",
        "example": "http://example.com/something.do?url=http%3A%2F%2Fexample.com%2Ftest%2Findex.html%3Ffoo%3Dbar%26fu%3Dbaz"
      }
    }
  },
  "opt_guide_operations_examples_code_5": {
    "message": "I am currently viewing $SYNTAX$.",
    "description": "Text for the 5th code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "syntax": {
        "content": "&quot;{#segment}-1{/segment}&quot;",
        "example": "\"{#segment}-1{/segment}\""
      }
    }
  },
  "opt_guide_operations_examples_code_6": {
    "message": "I am currently viewing $SYNTAX$.",
    "description": "Text for the 6th code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "syntax": {
        "content": "&quot;index.html&quot;",
        "example": "\"index.html\""
      }
    }
  },
  "opt_guide_operations_examples_code_7": {
    "message": "The value of $PARAM$ is $SYNTAX_1$$PARAM$$SYNTAX_2$.",
    "description": "Text for the 7th code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "param": {
        "content": "foo",
        "example": "foo"
      },
      "syntax_1": {
        "content": "&quot;{#param}",
        "example": "\"{#param}"
      },
      "syntax_2": {
        "content": "{/param}&quot;",
        "example": "{/param}\""
      }
    }
  },
  "opt_guide_operations_examples_code_8": {
    "message": "The value of $PARAM$ is $SYNTAX$.",
    "description": "Text for the 8th code block in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "param": {
        "content": "foo",
        "example": "foo"
      },
      "syntax": {
        "content": "&quot;bar&quot;",
        "example": "\"bar\""
      }
    }
  },
  "opt_guide_operations_examples_text_1": {
    "message": "These examples will be using the following $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$;",
    "description": "Text for the 1st paragraph in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_operations_examples_text_2": {
    "message": "To output the current date &amp; time in $O_LINK_ISO_8601$ISO 8601$C_LINK$ format you would use;",
    "description": "Text for the 2nd paragraph in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_iso_8601": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/ISO_8601\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/ISO_8601\">"
      }
    }
  },
  "opt_guide_operations_examples_text_3": {
    "message": "Also, the $O_EMPH$c$C_EMPH$ parameter would also have the same outcome in this case. If you wanted to safely pass the whole $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ as a parameter in a query string;",
    "description": "Text for the 3rd paragraph in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      }
    }
  },
  "opt_guide_operations_examples_text_4": {
    "message": "This escapes all of the necessary characters within $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ and outputs the following;",
    "description": "Text for the 4th paragraph in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_operations_examples_text_5": {
    "message": "To access the last segment of the $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$'s path;",
    "description": "Text for the 5th paragraph in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_operations_examples_text_6": {
    "message": "Would render the following output;",
    "description": "Text for the 6th paragraph in the Examples area on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_examples_text_7": {
    "message": "Accessing the value of the $PARAM$ parameter is as simple as the following;",
    "description": "Text for the 7th paragraph in the Examples area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "param": {
        "content": "<em>foo</em>",
        "example": "foo"
      }
    }
  },
  "opt_guide_operations_examples_text_8": {
    "message": "This would cause the following output to be rendered;",
    "description": "Text for the 8th paragraph in the Examples area on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_fparam_text": {
    "message": "Get the value of the parameter provided from within the hash fragment",
    "description": "Description of the fparam variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_fsegment_text": {
    "message": "Get the segment at the index provided from within the hash fragment",
    "description": "Description of the fsegment variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_header": {
    "message": "Operations",
    "description": "Header for the Operations section on the Guide tab of the Options page."
  },
  "opt_guide_operations_last_modified_text_1": {
    "message": "Format the last modified date &amp; time of the page using the pattern provided",
    "description": "1st line of the description of the lastModified variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_last_modified_text_2": {
    "message": "(see $O_LINK_PHP_DATE$$O_ABBR_1$Hypertext Preprocessor$O_ABBR_2$PHP$C_ABBR$s date$C_LINK$ for more details)",
    "description": "2nd line of the description of the lastModified variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_php_date": {
        "content": "<a href=\"http://php.net/manual/en/function.date.php#refsect1-function.date-parameters\" target=\"_blank\">",
        "example": "<a href=\"http://php.net/manual/en/function.date.php#refsect1-function.date-parameters\">"
      }
    }
  },
  "opt_guide_operations_length_text": {
    "message": "Get the character length of the text provided",
    "description": "Description of the length variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_lower_case_text": {
    "message": "Transform the text provided into lower case",
    "description": "Description of the lowerCase variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_meta_text": {
    "message": "Get the content of the page's meta information with the text provided",
    "description": "Description of the meta variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_notes_text_1": {
    "message": "The following notes only apply to $SEGMENT_LABEL$ and $FSEGMENT_LABEL$ operations;",
    "description": "1st paragraph for the Notes area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "fsegment_label": {
        "content": "<span class=\"label\">fsegment</span>",
        "example": "fsegment"
      },
      "segment_label": {
        "content": "<span class=\"label\">segment</span>",
        "example": "segment"
      }
    }
  },
  "opt_guide_operations_notes_text_2": {
    "message": "The count is not zero-indexed like an array (e.g. $SYNTAX$ returns the first segment)",
    "description": "Text for the 1st list item in the Notes area on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "syntax": {
        "content": "<code>{#segment}1{/segment}</code>",
        "example": "{#segment}1{/segment}"
      }
    }
  },
  "opt_guide_operations_notes_text_3": {
    "message": "The argument can be negative values, in which case it will count back from the end of the path rather than forwards from the start",
    "description": "Text for the 2nd list item in the Notes area on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_param_text": {
    "message": "Get the value of the parameter provided",
    "description": "Description of the param variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_segment_text": {
    "message": "Get the segment at the index provided",
    "description": "Description of the segment variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_select_all_html_text": {
    "message": "Concatenate the $O_ABBR_1$HyperText Markup Language$O_ABBR_2$HTML$C_ABBR$ contents of all matching elements",
    "description": "Description of the selectAllHTML variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_operations_select_all_markdown_text": {
    "message": "Concatenate the contents of all matching elements as $O_LINK_MARKDOWN$Markdown$C_LINK$",
    "description": "Description of the selectAllMarkdown variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_markdown": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/Markdown\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/Markdown\">"
      }
    }
  },
  "opt_guide_operations_select_all_text": {
    "message": "Concatenate the text of all matching elements",
    "description": "Description of the selectAll variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_select_html_text": {
    "message": "Get the $O_ABBR_1$HyperText Markup Language$O_ABBR_2$HTML$C_ABBR$ contents of the first matching element",
    "description": "Description of the selectHTML variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_operations_select_markdown_text": {
    "message": "Get the contents of the first matching element as $O_LINK_MARKDOWN$Markdown$C_LINK$",
    "description": "Description of the selectMarkdown variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_markdown": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/Markdown\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/Markdown\">"
      }
    }
  },
  "opt_guide_operations_select_text": {
    "message": "Get the text of first matching element",
    "description": "Description of the select variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_shorten_text": {
    "message": "Shorten the $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ provided using the active $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ shortener",
    "description": "Description of the shorten variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_operations_text": {
    "message": "$O_BOLD$Operations$C_BOLD$ are performed using sections, accepting its rendered contents as an argument.",
    "description": "Text for the Operations section on the Guide tab of the Options page.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_operations_tidy_text": {
    "message": "Reduce all of the joined spaces and tabs into single spaces within the text provided before removing all leading and trailing whitespace",
    "description": "Description of the tidy variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_trim_text": {
    "message": "Remove all leading and trailing whitespace from the text provided",
    "description": "Description of the trim variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_trim_left_text": {
    "message": "Remove all leading whitespace from the text provided",
    "description": "Description of the trimLeft variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_trim_right_text": {
    "message": "Remove all trailing whitespace from the text provided",
    "description": "Description of the trimRight variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_unescape_text": {
    "message": "The opposite of $ESCAPE_LABEL$; Replace escaped characters in text provided with their unescaped counterparts",
    "description": "Description of the unescape variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "escape_label": {
        "content": "<span class=\"label\">escape</span>",
        "example": "escape"
      }
    }
  },
  "opt_guide_operations_upper_case_text": {
    "message": "Transform the text provided into upper case",
    "description": "Description of the upperCase variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_word_count_text": {
    "message": "Get the number of words in the text provided",
    "description": "Description of the wordCount variable on the Guide tab of the Options page under the Operations section."
  },
  "opt_guide_operations_xpath_all_html_text": {
    "message": "Concatenate the $O_ABBR_1$HyperText Markup Language$O_ABBR_2$HTML$C_ABBR$ contents of all results for the $O_LINK_XPATH$XPath$C_LINK$ expression",
    "description": "Description of the xpathAllHTML variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_xpath": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/XPath\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/XPath\">"
      }
    }
  },
  "opt_guide_operations_xpath_all_markdown_text": {
    "message": "Concatenate the contents of all results for the $O_LINK_XPATH$XPath$C_LINK$ expression as $O_LINK_MARKDOWN$Markdown$C_LINK$",
    "description": "Description of the xpathAllMarkdown variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_markdown": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/Markdown\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/Markdown\">"
      },
      "o_link_xpath": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/XPath\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/XPath\">"
      }
    }
  },
  "opt_guide_operations_xpath_all_text": {
    "message": "Concatenate all results for the $O_LINK_XPATH$XPath$C_LINK$ expression",
    "description": "Description of the xpathAll variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_xpath": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/XPath\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/XPath\">"
      }
    }
  },
  "opt_guide_operations_xpath_html_text": {
    "message": "Get the $O_ABBR_1$HyperText Markup Language$O_ABBR_2$HTML$C_ABBR$ contents of the first result for the $O_LINK_XPATH$XPath$C_LINK$ expression",
    "description": "Description of the xpathHTML variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_xpath": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/XPath\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/XPath\">"
      }
    }
  },
  "opt_guide_operations_xpath_markdown_text": {
    "message": "Get the contents of the first result for the $O_LINK_XPATH$XPath$C_LINK$ expression as $O_LINK_MARKDOWN$Markdown$C_LINK$",
    "description": "Description of the xpathMarkdown variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_markdown": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/Markdown\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/Markdown\">"
      },
      "o_link_xpath": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/XPath\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/XPath\">"
      }
    }
  },
  "opt_guide_operations_xpath_text": {
    "message": "Get the first result for the $O_LINK_XPATH$XPath$C_LINK$ expression as text",
    "description": "Description of the xpath variable on the Guide tab of the Options page under the Operations section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_xpath": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/XPath\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/XPath\">"
      }
    }
  },
  "opt_guide_options_header": {
    "message": "Options",
    "description": "Header for the Options section on the Guide tab of the Options page."
  },
  "opt_guide_options_bitly_account_text": {
    "message": "Whether or not you are currently logged in to your $O_LINK_BITLY$bit.ly$C_LINK$ account",
    "description": "Description of the bitlyAccount variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_bitly": {
        "content": "<a href=\"http://bit.ly\" target=\"_blank\">",
        "example": "<a href=\"http://bit.ly\">"
      }
    }
  },
  "opt_guide_options_bitly_text": {
    "message": "Whether or not $O_LINK_BITLY$bit.ly$C_LINK$ is the enabled $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ shortener",
    "description": "Description of the bitly variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_bitly": {
        "content": "<a href=\"http://bit.ly\" target=\"_blank\">",
        "example": "<a href=\"http://bit.ly\">"
      }
    }
  },
  "opt_guide_options_examples_code_1": {
    "message": "$URL$",
    "description": "Text for the 1st code block in the Examples area on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "url": {
        "content": "http://example.com/test/index.html",
        "example": "http://example.com/test/index.html"
      }
    }
  },
  "opt_guide_options_examples_code_2": {
    "message": "$SYNTAX_1$This is a test!$SYNTAX_2$",
    "description": "Text for the 2nd code block in the Examples area on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "syntax_1": {
        "content": "&lt;a href=&quot;{url}&quot;{#linksTitle} title=&quot;{{title}}&quot;{/linksTitle}&gt;",
        "example": "<a href=\"{url}\"{#linksTitle} title=\"{{title}}\"{/linksTitle}>"
      },
      "syntax_2": {
        "content": "&lt;/a&gt;",
        "example": "</a>"
      }
    }
  },
  "opt_guide_options_examples_code_3": {
    "message": "$SYNTAX_1$Test$SYNTAX_2$This is a test!$SYNTAX_3$",
    "description": "Text for the 3rd code block in the Examples area on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "syntax_1": {
        "content": "&lt;a href=&quot;http://example.com/test/index.html&quot; title=&quot;",
        "example": "<a href=\"http://example.com/test/index.html\" title=\""
      },
      "syntax_2": {
        "content": "&quot;&gt;",
        "example": "\">"
      },
      "syntax_3": {
        "content": "&lt;/a&gt;",
        "example": "</a>"
      }
    }
  },
  "opt_guide_options_examples_code_4": {
    "message": "$SYNTAX_1$This is a test!$SYNTAX_2$",
    "description": "Text for the 4th code block in the Examples area on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "syntax_1": {
        "content": "&lt;a href=&quot;http://example.com/test/index.html&quot;&gt;",
        "example": "<a href=\"http://example.com/test/index.html\">"
      },
      "syntax_2": {
        "content": "&lt;/a&gt;",
        "example": "</a>"
      }
    }
  },
  "opt_guide_options_examples_text_1": {
    "message": "These examples will be using the following $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$;",
    "description": "Text for the 1st paragraph in the Examples area on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_options_examples_text_2": {
    "message": "To include the $SYNTAX$ attribute in an anchor tag only if you have enabled the corresponding option;",
    "description": "Text for the 2nd paragraph in the Examples area on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "syntax": {
        "content": "<em>title</em>",
        "example": "title"
      }
    }
  },
  "opt_guide_options_examples_text_3": {
    "message": "This would output the following if you've enabled the option;",
    "description": "Text for the 3rd paragraph in the Examples area on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_examples_text_4": {
    "message": "However, if you have disabled the option it will output this;",
    "description": "Text for the 4th paragraph in the Examples area on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_googl_account_text": {
    "message": "Whether or not you are currently logged in to your $O_LINK_GOOGL$goo.gl$C_LINK$ account",
    "description": "Description of the googlAccount variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_googl": {
        "content": "<a href=\"http://goo.gl\" target=\"_blank\">",
        "example": "<a href=\"http://goo.gl\">"
      }
    }
  },
  "opt_guide_options_googl_text": {
    "message": "Whether or not $O_LINK_GOOGL$goo.gl$C_LINK$ is the enabled $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ shortener",
    "description": "Description of the googl variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_googl": {
        "content": "<a href=\"http://goo.gl\" target=\"_blank\">",
        "example": "<a href=\"http://goo.gl\">"
      }
    }
  },
  "opt_guide_options_links_target_text": {
    "message": "Whether or not the option to render links with instructions to open them in a new tab/window is enabled",
    "description": "Description of the linksTarget variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_links_title_text": {
    "message": "Whether or not the option to render links with hover text is enabled",
    "description": "Description of the linksTitle variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_markdown_inline_text": {
    "message": "Whether or not the option to render $O_LINK_MARKDOWN$Markdown$C_LINK$ links using the inline style is enabled",
    "description": "Description of the markdownInline variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_markdown": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/Markdown\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/Markdown\">"
      }
    }
  },
  "opt_guide_options_menu_text": {
    "message": "Whether or not the option to show the context (right-click) menu is enabled",
    "description": "Description of the menu variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_menu_options_text": {
    "message": "Whether or not the $O_EMPH$Options$C_EMPH$ item is displayed at the bottom of the context (right-click) menu",
    "description": "Description of the menuOptions variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      }
    }
  },
  "opt_guide_options_menu_paste_text": {
    "message": "Whether or not the Template output is automatically pasted into the field where the context (right-click) menu was activated",
    "description": "Description of the menuPaste variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_notifications_text": {
    "message": "Whether or not the option to show desktop notifications is enabled",
    "description": "Description of the notifications variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_shortcuts_paste_text": {
    "message": "Whether or not the Template output is automatically pasted into the field where the keyboard shortcut was detected",
    "description": "Description of the shortcutsPaste variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_shortcuts_text": {
    "message": "Whether or not the option to allow keyboard shortcuts is enabled",
    "description": "Description of the shortcuts variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_text": {
    "message": "$O_BOLD$Options$C_BOLD$ are variables that represent your current $O_BOLD$Template$C_BOLD$ settings and are generally accessed in the same way as standard variables.",
    "description": "Text for the Options section on the Guide tab of the Options page.",
    "placeholders": {
      "c_bold": {
        "content": "</strong>",
        "example": "</strong>"
      },
      "o_bold": {
        "content": "<strong>",
        "example": "<strong>"
      }
    }
  },
  "opt_guide_options_toolbar_close_text": {
    "message": "Whether or not the popup is closed immediately after a template is selected",
    "description": "Description of the toolbarClose variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_toolbar_key_text": {
    "message": "The unique key of the template activated when the toolbar button is clicked",
    "description": "Description of the toolbarKey variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_toolbar_options_text": {
    "message": "Whether or not the $O_EMPH$Options$C_EMPH$ link is displayed at the bottom of the popup",
    "description": "Description of the toolbarOptions variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      }
    }
  },
  "opt_guide_options_toolbar_popup_text": {
    "message": "Whether or not the popup is shown when the toolbar button is clicked",
    "description": "Description of the toolbarPopup variable on the Guide tab of the Options page under the Options section."
  },
  "opt_guide_options_yourls_authentication_text": {
    "message": "The authentication used for the $O_LINK_YOURLS$YOURLS$C_LINK$ service (e.g. $EXAMPLE_1$, $EXAMPLE_2$, or nothing if $EXAMPLE_3$)",
    "description": "Description of the yourlsAuthentication variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "example_1": {
        "content": "<em>advanced</em>",
        "example": "advanced"
      },
      "example_2": {
        "content": "<em>basic</em>",
        "example": "basic"
      },
      "example_3": {
        "content": "<em>none</em>",
        "example": "none"
      },
      "o_link_yourls": {
        "content": "<a href=\"http://yourls.org\" target=\"_blank\">",
        "example": "<a href=\"http://yourls.org\">"
      }
    }
  },
  "opt_guide_options_yourls_password_text": {
    "message": "The password for the $O_LINK_YOURLS$YOURLS$C_LINK$ service",
    "description": "Description of the yourlsPassword variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_yourls": {
        "content": "<a href=\"http://yourls.org\" target=\"_blank\">",
        "example": "<a href=\"http://yourls.org\">"
      }
    }
  },
  "opt_guide_options_yourls_signature_text": {
    "message": "The signature for the $O_LINK_YOURLS$YOURLS$C_LINK$ service (e.g. $EXAMPLE$)",
    "description": "Description of the yourlsSignature variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "example": {
        "content": "<em>3002a61584</em>",
        "example": "3002a61584"
      },
      "o_link_yourls": {
        "content": "<a href=\"http://yourls.org\" target=\"_blank\">",
        "example": "<a href=\"http://yourls.org\">"
      }
    }
  },
  "opt_guide_options_yourls_text": {
    "message": "Whether or not $O_LINK_YOURLS$YOURLS$C_LINK$ is the enabled $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ shortener",
    "description": "Description of the yourls variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_yourls": {
        "content": "<a href=\"http://yourls.org\" target=\"_blank\">",
        "example": "<a href=\"http://yourls.org\">"
      }
    }
  },
  "opt_guide_options_yourls_url_text": {
    "message": "The $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ of the $O_LINK_YOURLS$YOURLS$C_LINK$ service (e.g. $EXAMPLE$)",
    "description": "Description of the yourlsUrl variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "example": {
        "content": "<em>http://example.com/yourls-api.php</em>",
        "example": "http://example.com/yourls-api.php"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "o_link_yourls": {
        "content": "<a href=\"http://yourls.org\" target=\"_blank\">",
        "example": "<a href=\"http://yourls.org\">"
      }
    }
  },
  "opt_guide_options_yourls_username_text": {
    "message": "The username for the $O_LINK_YOURLS$YOURLS$C_LINK$ service",
    "description": "Description of the yourlsUsername variable on the Guide tab of the Options page under the Options section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_yourls": {
        "content": "<a href=\"http://yourls.org\" target=\"_blank\">",
        "example": "<a href=\"http://yourls.org\">"
      }
    }
  },
  "opt_guide_standard_author_text": {
    "message": "The author from the page's meta information",
    "description": "Description of the author variable on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_base_text": {
    "message": "The base domain (e.g. $EXAMPLE$)",
    "description": "Description of the base variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "example": {
        "content": "<em>https://www.example.com:443</em>",
        "example": "https://www.example.com:443"
      }
    }
  },
  "opt_guide_standard_browser_text": {
    "message": "The name of the browser (i.e. $O_EMPH$Chrome$C_EMPH$)",
    "description": "Description of the browser variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_emph": {
        "content": "</em>",
        "example": "</em>"
      },
      "o_emph": {
        "content": "<em>",
        "example": "<em>"
      }
    }
  },
  "opt_guide_standard_browser_version_text": {
    "message": "The current version of the browser (e.g. $EXAMPLE$)",
    "description": "Description of the browserVersion variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "example": {
        "content": "<em>16.0.912.77</em>",
        "example": "16.0.912.77"
      }
    }
  },
  "opt_guide_standard_character_set_text": {
    "message": "The $O_LINK_CHAR_SET$character set$C_LINK$ used by the page (e.g. $EXAMPLE$)",
    "description": "Description of the characterSet variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "example": {
        "content": "<em>UTF-8</em>",
        "example": "UTF-8"
      },
      "o_link_char_set": {
        "content": "<a href=\"http://www.iana.org/assignments/character-sets\" target=\"_blank\">",
        "example": "<a href=\"http://www.iana.org/assignments/character-sets\">"
      }
    }
  },
  "opt_guide_standard_cookies_enabled_text": {
    "message": "Whether or not cookies are enabled",
    "description": "Description of the cookiesEnabled variable on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_count_text": {
    "message": "The total number of templates",
    "description": "Description of the count variable on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_custom_count_text": {
    "message": "The total number of user-defined templates",
    "description": "Description of the customCount variable on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_date_time_text": {
    "message": "The current date &amp; time in $O_LINK_RFC_2822$RFC 2822$C_LINK$ format",
    "description": "Description of the dateTime variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_rfc_2822": {
        "content": "<a href=\"http://www.faqs.org/rfcs/rfc2822.html\" target=\"_blank\">",
        "example": "<a href=\"http://www.faqs.org/rfcs/rfc2822.html\">"
      }
    }
  },
  "opt_guide_standard_depth_text": {
    "message": "The colour depth in bits (e.g. $EXAMPLE$)",
    "description": "Description of the depth variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "example": {
        "content": "<em>24</em>",
        "example": "24"
      }
    }
  },
  "opt_guide_standard_description_text": {
    "message": "The description from the page's meta information",
    "description": "Description of the description variable on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_directory_text": {
    "message": "The directory part of the path (e.g. $EXAMPLE$)",
    "description": "Description of the directory variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "example": {
        "content": "<em>/folder/dir/</em>",
        "example": "/folder/dir/"
      }
    }
  },
  "opt_guide_standard_examples_code_1": {
    "message": "$URL$",
    "description": "Text for the 1st code block in the Examples area on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "url": {
        "content": "http://example.com/test/index.html",
        "example": "http://example.com/test/index.html"
      }
    }
  },
  "opt_guide_standard_examples_code_2": {
    "message": "Title:\n$SYNTAX_1$\nDescription:\n$SYNTAX_2$\n$SYNTAX_3$N/A$SYNTAX_4$",
    "description": "Text for the 2nd code block in the Examples area on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "syntax_1": {
        "content": "{title}",
        "example": "{title}"
      },
      "syntax_2": {
        "content": "{#description}{description}{/description}",
        "example": "{#description}{description}{/description}"
      },
      "syntax_3": {
        "content": "{^description}",
        "example": "{^description}"
      },
      "syntax_4": {
        "content": "{/description}",
        "example": "{/description}"
      }
    }
  },
  "opt_guide_standard_examples_code_3": {
    "message": "Title:\nTest\nDescription:\nThis is a test!",
    "description": "Text for the 3rd code block in the Examples area on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_examples_code_4": {
    "message": "Title:\nTest\nDescription:\nN/A",
    "description": "Text for the 4th code block in the Examples area on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_examples_text_1": {
    "message": "These examples will be using the following $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$;",
    "description": "Text for the 1st paragraph in the Examples area on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_standard_examples_text_2": {
    "message": "A great of example of using standard variables is showing the title of the current page along with its meta description, where possible;",
    "description": "Text for the 2nd paragraph in the Examples area on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_examples_text_3": {
    "message": "If the page contains a meta description this would output something like this;",
    "description": "Text for the 3rd paragraph in the Examples area on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_examples_text_4": {
    "message": "Otherwise, you can expect to the see the following;",
    "description": "Text for the 4th paragraph in the Examples area on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_favicon_text": {
    "message": "The whole $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ of the page's favicon",
    "description": "Description of the favicon variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_standard_file_text": {
    "message": "The basename of the file (e.g. $EXAMPLE$)",
    "description": "Description of the file variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "example": {
        "content": "<em>index.html</em>",
        "example": "index.html"
      }
    }
  },
  "opt_guide_standard_fragment_anchor_text": {
    "message": "The entire string after the hash (#) symbol",
    "description": "Description of the fragment and anchor variables on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_header": {
    "message": "Standard",
    "description": "Header for the Standard section on the Guide tab of the Options page."
  },
  "opt_guide_standard_host_text": {
    "message": "For example; $EXAMPLE_1$, $EXAMPLE_2$",
    "description": "Description of the host variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "example_1": {
        "content": "<em>www.example.com</em>",
        "example": "www.example.com"
      },
      "example_2": {
        "content": "<em>localhost</em>",
        "example": "localhost"
      }
    }
  },
  "opt_guide_standard_html_text": {
    "message": "The entire $O_ABBR_1$HyperText Markup Language$O_ABBR_2$HTML$C_ABBR$ contents of the page",
    "description": "Description of the html variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_standard_java_text": {
    "message": "Whether or not $O_LINK_JAVA$Java$C_LINK$ is enabled",
    "description": "Description of the java variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_java": {
        "content": "<a href=\"http://www.java.com\" target=\"_blank\">",
        "example": "<a href=\"http://www.java.com\">"
      }
    }
  },
  "opt_guide_standard_last_modified_text": {
    "message": "The last modified date &amp; time of the page in $O_LINK_RFC_2822$RFC 2822$C_LINK$ format",
    "description": "Description of the lastModified variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_rfc_2822": {
        "content": "<a href=\"http://www.faqs.org/rfcs/rfc2822.html\" target=\"_blank\">",
        "example": "<a href=\"http://www.faqs.org/rfcs/rfc2822.html\">"
      }
    }
  },
  "opt_guide_standard_link_html_text": {
    "message": "The $O_ABBR_1$Hypertext Markup Language$O_ABBR_2$HTML$C_ABBR$ behind the contextual (right-clicked) link",
    "description": "Description of the linkHTML variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      }
    }
  },
  "opt_guide_standard_link_markdown_text": {
    "message": "The contents of the contextual (right-clicked) link formatted as $O_LINK_MARKDOWN$Markdown$C_LINK$",
    "description": "Description of the linkMarkdown variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_markdown": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/Markdown\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/Markdown\">"
      }
    }
  },
  "opt_guide_standard_link_text_text": {
    "message": "The contextual (right-clicked) link text",
    "description": "Description of the linkText variable on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_locale_text": {
    "message": "The $O_LINK_ISO_639$ISO 639$C_LINK$ code for the detected page language",
    "description": "Description of the locale variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_iso_639": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/ISO_639_macrolanguage\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/ISO_639_macrolanguage\">"
      }
    }
  },
  "opt_guide_standard_markdown_text": {
    "message": "The entire contents of the page as $O_LINK_MARKDOWN$Markdown$C_LINK$",
    "description": "Description of the markdown variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_link": {
        "content": "</a>",
        "example": "</a>"
      },
      "o_link_markdown": {
        "content": "<a href=\"http://en.wikipedia.org/wiki/Markdown\" target=\"_blank\">",
        "example": "<a href=\"http://en.wikipedia.org/wiki/Markdown\">"
      }
    }
  },
  "opt_guide_standard_offline_text": {
    "message": "Whether or not you are currently offline",
    "description": "Description of the offline variable on the Guide tab of the Options page under the Standard section."
  },
  "opt_guide_standard_original_title_text": {
    "message": "The original title of the page (may be different than $TITLE_LABEL$ if a supported extension was detected and the value of $TITLE_LABEL$ was extracted from this)",
    "description": "Description of the originalTitle variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "title_label": {
        "content": "<span class=\"label\">title</span>",
        "example": "title"
      }
    }
  },
  "opt_guide_standard_original_url_text": {
    "message": "The original whole $O_ABBR_1$Uniform Resource Locator$O_ABBR_2$URL$C_ABBR$ being parsed (may be different than $URL_LABEL$ if a supported extension was detected and the value of $URL_LABEL$ was extracted from this)",
    "description": "Description of the originalUrl variable on the Guide tab of the Options page under the Standard section.",
    "placeholders": {
      "c_abbr": {
        "content": "</abbr>",
        "example": "</abbr>"
      },
      "o_abbr_1": {
        "content": "<abbr title=\"",
        "example": "<abbr title=\""
      },
      "o_abbr_2": {
        "content": "\">",
        "example": "\">"
      },
      "url_label": {
        "content": "<span class=\"label\">url</span>",
        "example": "url"
      }
    }
  },
  "opt_guide_standard_os_text": {
    "message": "The family of your 
Download .txt
gitextract_t6167sma/

├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.md
│       ├── custom.md
│       └── feature_request.md
├── .gitignore
├── .prettierrc.js
├── CONTRIBUTING.md
├── LICENSE
├── README-zh_CN.md
├── README.md
├── commitlint.config.js
├── examples/
│   ├── README.md
│   ├── chrome-extension/
│   │   ├── README.md
│   │   ├── _locales/
│   │   │   └── en/
│   │   │       └── messages.json
│   │   ├── feed.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── transmart.config.js
│   └── next.js/
│       ├── @types/
│       │   └── i18next.d.ts
│       ├── components/
│       │   ├── Footer.tsx
│       │   └── Header.tsx
│       ├── next-env.d.ts
│       ├── next-i18next.config.js
│       ├── next-utils.config.js
│       ├── next.config.js
│       ├── package.json
│       ├── pages/
│       │   ├── _app.tsx
│       │   ├── _document.tsx
│       │   ├── index.tsx
│       │   └── second-page.tsx
│       ├── public/
│       │   ├── app.css
│       │   └── locales/
│       │       └── en/
│       │           ├── common.json
│       │           ├── footer.json
│       │           └── second-page.json
│       ├── transmart.config.js
│       ├── tsconfig.json
│       └── vercel.json
├── lerna.json
├── package.json
├── packages/
│   ├── cli/
│   │   ├── README.md
│   │   ├── bin/
│   │   │   └── transmart.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── cli.ts
│   │   │   ├── index.ts
│   │   │   ├── options.ts
│   │   │   └── types.ts
│   │   └── tsconfig.build.json
│   └── core/
│       ├── README.md
│       ├── package.json
│       ├── src/
│       │   ├── index.ts
│       │   ├── language.ts
│       │   ├── limit.ts
│       │   ├── split.ts
│       │   ├── task.ts
│       │   ├── translate.ts
│       │   ├── transmart.ts
│       │   ├── types.ts
│       │   └── util.ts
│       ├── test/
│       │   └── locales/
│       │       ├── de/
│       │       │   ├── common.json
│       │       │   └── tos.json
│       │       ├── en/
│       │       │   ├── common.json
│       │       │   ├── large-file.json
│       │       │   └── tos.json
│       │       ├── jp/
│       │       │   └── common.json
│       │       ├── zh-CN/
│       │       │   ├── common.json
│       │       │   ├── large-file.json
│       │       │   └── tos.json
│       │       └── zh-TW/
│       │           ├── common.json
│       │           └── tos.json
│       └── tsconfig.build.json
└── tsconfig.json
Download .txt
SYMBOL INDEX (38 symbols across 15 files)

FILE: examples/next.js/@types/i18next.d.ts
  type I18nNamespaces (line 14) | interface I18nNamespaces {
  type CustomTypeOptions (line 21) | interface CustomTypeOptions {

FILE: examples/next.js/components/Header.tsx
  type Props (line 4) | type Props = {

FILE: examples/next.js/pages/_document.tsx
  type Props (line 10) | type Props = DocumentProps & {
  class MyDocument (line 14) | class MyDocument extends Document<Props> {
    method render (line 15) | render() {

FILE: examples/next.js/pages/index.tsx
  type Props (line 11) | type Props = {

FILE: examples/next.js/pages/second-page.tsx
  type Props (line 13) | type Props = {

FILE: packages/cli/src/cli.ts
  function run (line 7) | async function run(options: CmdOptions) {

FILE: packages/cli/src/options.ts
  function parseArgv (line 49) | async function parseArgv(args: Array<string>): Promise<CmdOptions | null> {

FILE: packages/cli/src/types.ts
  type CmdOptions (line 3) | type CmdOptions = TransmartOptions & {

FILE: packages/core/src/language.ts
  function getLanguageDisplayName (line 1) | function getLanguageDisplayName(code: string) {

FILE: packages/core/src/limit.ts
  constant CONCURRENCY (line 3) | const CONCURRENCY = 5

FILE: packages/core/src/split.ts
  function splitJSONtoSmallChunks (line 3) | function splitJSONtoSmallChunks(
  function isPlainObject (line 49) | function isPlainObject(obj: unknown): obj is Record<string, unknown> {
  function getJSONTokenSize (line 53) | function getJSONTokenSize(object: Record<string, unknown>, depth = 0): n...
  function getPrimitiveValueSize (line 77) | function getPrimitiveValueSize(value: any): number {

FILE: packages/core/src/task.ts
  type TaskResult (line 9) | interface TaskResult {
  class Task (line 14) | class Task {
    method constructor (line 15) | constructor(private transmart: Transmart, private work: RunWork) {}
    method start (line 17) | async start(onProgress: (current: number, total: number) => any) {
    method run (line 53) | private async run(content: string, index: number): Promise<TaskResult> {
    method parse (line 84) | parse(content: string): Record<string, any> {
    method pack (line 95) | pack(result: TaskResult[]): Record<string, any> {

FILE: packages/core/src/translate.ts
  function translate (line 5) | async function translate(params: TranslateParams, retryTime = 0): Promis...

FILE: packages/core/src/transmart.ts
  constant DEFAULT_PARAMS (line 9) | const DEFAULT_PARAMS: Partial<TransmartOptions> = {
  class Transmart (line 17) | class Transmart {
    method constructor (line 19) | constructor(options: TransmartOptions) {
    method run (line 23) | public async run(options: RunOptions): Promise<TransmartStats> {
    method processSingleNamespace (line 149) | private async processSingleNamespace(work: RunWork, options: RunOption...
    method validateParams (line 163) | private validateParams() {

FILE: packages/core/src/types.ts
  type TransmartOptions (line 1) | interface TransmartOptions {
  type Stats (line 93) | interface Stats {
  type TransmartStats (line 99) | interface TransmartStats {
  type TranslateParams (line 105) | interface TranslateParams {
  type TranslateResult (line 119) | interface TranslateResult {
  type RunOptions (line 128) | interface RunOptions {
  type RunWork (line 134) | interface RunWork {
Condensed preview — 73 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (433K chars).
[
  {
    "path": ".editorconfig",
    "chars": 636,
    "preview": "# http://editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_tr"
  },
  {
    "path": ".eslintignore",
    "chars": 9,
    "preview": "examples\n"
  },
  {
    "path": ".eslintrc",
    "chars": 414,
    "preview": "{\n  \"root\": true,\n  \"parser\": \"@typescript-eslint/parser\",\n  \"env\": {\n    \"browser\": true,\n    \"node\": true,\n    \"es6\": "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 834,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/custom.md",
    "chars": 126,
    "preview": "---\nname: Custom issue template\nabout: Describe this issue template's purpose here.\ntitle: ''\nlabels: ''\nassignees: ''\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".gitignore",
    "chars": 3049,
    "preview": "# Created by https://www.toptal.com/developers/gitignore/api/node,macOS\n# Edit at https://www.toptal.com/developers/giti"
  },
  {
    "path": ".prettierrc.js",
    "chars": 411,
    "preview": "module.exports = {\n  printWidth: 120,\n  tabWidth: 2,\n  useTabs: false,\n  semi: false,\n  singleQuote: true,\n  quoteProps:"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 204,
    "preview": "# Contributing to Transmart\n\n1. Fork this repo\n\n2. Clone your forked repo\n\n3. Run it\n\n```\nnpm install\nnpm run build:watc"
  },
  {
    "path": "LICENSE",
    "chars": 1067,
    "preview": "MIT License\n\nCopyright (c) 2023 Quill Zhou\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
  },
  {
    "path": "README-zh_CN.md",
    "chars": 4118,
    "preview": "<p align=\"center\">\n  <img src=\"./assets/logo.png\" />\n</p>\n\n<p align=\"center\">\n<b> Transmart - 利用 AI 自动化您的 i18n</b>\n</p>\n"
  },
  {
    "path": "README.md",
    "chars": 9656,
    "preview": "<p align=\"center\">\n  <img src=\"./assets/logo.png\" />\n</p>\n\n<p align=\"center\">\n  <b>Transmart - Automate your i18n locali"
  },
  {
    "path": "commitlint.config.js",
    "chars": 69,
    "preview": "module.exports = {\n  extends: ['@commitlint/config-conventional'],\n}\n"
  },
  {
    "path": "examples/README.md",
    "chars": 305,
    "preview": "This Folder contain All examples using transmart\n\nSince we need to use the OpenAI API key, we need to load it into the e"
  },
  {
    "path": "examples/chrome-extension/README.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/chrome-extension/_locales/en/messages.json",
    "chars": 1570,
    "preview": "{\n  \"name\": {\n    \"message\": \"News Reader\",\n    \"description\": \"Extension name in manifest.\"\n  },\n  \"description\": {\n   "
  },
  {
    "path": "examples/chrome-extension/feed.html",
    "chars": 7948,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<style>\nbody {\n  font-family: helvetica, arial, sans-serif;\n  font-size: 12px;\n  overflow:"
  },
  {
    "path": "examples/chrome-extension/manifest.json",
    "chars": 397,
    "preview": "{\n  \"name\": \"__MSG_name__\",\n  \"version\": \"1.1\",\n  \"description\": \"__MSG_description__\",\n  \"icons\": { \"128\": \"news_icon.p"
  },
  {
    "path": "examples/chrome-extension/package.json",
    "chars": 260,
    "preview": "{\n  \"name\": \"chrome-extension\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"tra"
  },
  {
    "path": "examples/chrome-extension/transmart.config.js",
    "chars": 260,
    "preview": "// eslint-disable-next-line @typescript-eslint/no-var-requires\n\nmodule.exports = {\n  baseLocale: 'en',\n  locales: ['zh_C"
  },
  {
    "path": "examples/next.js/@types/i18next.d.ts",
    "chars": 642,
    "preview": "/**\n * If you want to enable locale keys typechecking and enhance IDE experience.\n *\n * Requires `resolveJsonModule:true"
  },
  {
    "path": "examples/next.js/components/Footer.tsx",
    "chars": 786,
    "preview": "import pkg from 'next-i18next/package.json'\nimport { useTranslation, Trans } from 'next-i18next'\nimport type { FC } from"
  },
  {
    "path": "examples/next.js/components/Header.tsx",
    "chars": 448,
    "preview": "import Head from 'next/head'\nimport type { FC } from 'react'\n\ntype Props = {\n  heading: string\n  title: string\n}\n\nexport"
  },
  {
    "path": "examples/next.js/next-env.d.ts",
    "chars": 201,
    "preview": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\n\n// NOTE: This file should not be edite"
  },
  {
    "path": "examples/next.js/next-i18next.config.js",
    "chars": 752,
    "preview": "// @ts-check\n\n/**\n * @type {import('next-i18next').UserConfig}\n */\nmodule.exports = {\n  // https://www.i18next.com/overv"
  },
  {
    "path": "examples/next.js/next-utils.config.js",
    "chars": 572,
    "preview": "const pc = require('picocolors')\n\nconst nextUtilsConfig = () => {\n  const trueEnv = ['true', '1', 'yes']\n  const esmExte"
  },
  {
    "path": "examples/next.js/next.config.js",
    "chars": 538,
    "preview": "// @ts-check\nconst { i18n } = require('./next-i18next.config.js')\n\n// You can remove the following 2 lines when integrat"
  },
  {
    "path": "examples/next.js/package.json",
    "chars": 840,
    "preview": "{\n  \"name\": \"v12\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"dev\": \"next\",\n   "
  },
  {
    "path": "examples/next.js/pages/_app.tsx",
    "chars": 375,
    "preview": "import type { AppProps } from 'next/app'\nimport { appWithTranslation } from 'next-i18next'\n// import nextI18NextConfig f"
  },
  {
    "path": "examples/next.js/pages/_document.tsx",
    "chars": 1398,
    "preview": "import Document, {\n  Html,\n  Head,\n  Main,\n  NextScript,\n} from 'next/document'\nimport type { DocumentProps } from 'next"
  },
  {
    "path": "examples/next.js/pages/index.tsx",
    "chars": 3596,
    "preview": "import Link from 'next/link'\nimport { useRouter } from 'next/router'\nimport type { GetStaticProps, InferGetStaticPropsTy"
  },
  {
    "path": "examples/next.js/pages/second-page.tsx",
    "chars": 1083,
    "preview": "import Link from 'next/link'\nimport type {\n  GetServerSideProps,\n  InferGetServerSidePropsType,\n} from 'next'\n\nimport { "
  },
  {
    "path": "examples/next.js/public/app.css",
    "chars": 1557,
    "preview": "#__next {\n  font-family: 'Open Sans', sans-serif;\n  text-align: center;\n  background-image: linear-gradient(\n    to left"
  },
  {
    "path": "examples/next.js/public/locales/en/common.json",
    "chars": 975,
    "preview": "{\n  \"h1\": \"A simple example\",\n  \"change-locale\": \"Change locale to \\\"{{changeTo}}\\\"\",\n  \"to-second-page\": \"To second pag"
  },
  {
    "path": "examples/next.js/public/locales/en/footer.json",
    "chars": 179,
    "preview": "{\n  \"description\": \"This is a non-page component that requires its own namespace\",\n  \"helpLocize\": \"With using <1>locize"
  },
  {
    "path": "examples/next.js/public/locales/en/second-page.json",
    "chars": 127,
    "preview": "{\n  \"h1\": \"A second page, to demonstrate routing\",\n  \"back-to-home\": \"Back to home\",\n  \"title\": \"Second page | next-i18n"
  },
  {
    "path": "examples/next.js/transmart.config.js",
    "chars": 323,
    "preview": "// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { i18n } = require('./next-i18next.config.js')\n\nmod"
  },
  {
    "path": "examples/next.js/tsconfig.json",
    "chars": 678,
    "preview": "{\n  \"$schema\": \"https://json.schemastore.org/tsconfig\",\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"lib\": [\"dom\""
  },
  {
    "path": "examples/next.js/vercel.json",
    "chars": 41,
    "preview": "{\n  \"github\": {\n    \"silent\": true\n  }\n}\n"
  },
  {
    "path": "lerna.json",
    "chars": 156,
    "preview": "{\n  \"$schema\": \"node_modules/lerna/schemas/lerna-schema.json\",\n  \"useWorkspaces\": true,\n  \"version\": \"0.5.3\",\n  \"registr"
  },
  {
    "path": "package.json",
    "chars": 1734,
    "preview": "{\n  \"name\": \"transmart\",\n  \"version\": \"0.0.1\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"lib/index.d.ts\",\n  \"description\":"
  },
  {
    "path": "packages/cli/README.md",
    "chars": 46,
    "preview": "[Docs](https://github.com/Quilljou/transmart)\n"
  },
  {
    "path": "packages/cli/bin/transmart.js",
    "chars": 45,
    "preview": "#!/usr/bin/env node\n\nrequire('../lib/index')\n"
  },
  {
    "path": "packages/cli/package.json",
    "chars": 850,
    "preview": "{\n  \"name\": \"@transmart/cli\",\n  \"version\": \"0.5.3\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"lib/index.d.ts\",\n  \"files\": "
  },
  {
    "path": "packages/cli/src/cli.ts",
    "chars": 1470,
    "preview": "import { CmdOptions } from './types'\nimport { Transmart } from '@transmart/core'\nimport * as fs from 'fs-extra'\nimport *"
  },
  {
    "path": "packages/cli/src/index.ts",
    "chars": 255,
    "preview": "import { parseArgv } from './options'\nimport { run } from './cli'\n\nparseArgv(process.argv).then((opts) => {\n  if (opts) "
  },
  {
    "path": "packages/cli/src/options.ts",
    "chars": 2640,
    "preview": "import { CmdOptions } from './types'\nimport { program } from 'commander'\nimport { cosmiconfig } from 'cosmiconfig'\nimpor"
  },
  {
    "path": "packages/cli/src/types.ts",
    "chars": 117,
    "preview": "import { TransmartOptions } from '@transmart/core'\n\nexport type CmdOptions = TransmartOptions & {\n  config: string\n}\n"
  },
  {
    "path": "packages/cli/tsconfig.build.json",
    "chars": 245,
    "preview": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"module\": \"CommonJS\",\n    \"outDir\""
  },
  {
    "path": "packages/core/README.md",
    "chars": 46,
    "preview": "[Docs](https://github.com/Quilljou/transmart)\n"
  },
  {
    "path": "packages/core/package.json",
    "chars": 771,
    "preview": "{\n  \"name\": \"@transmart/core\",\n  \"version\": \"0.5.3\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"lib/index.d.ts\",\n  \"files\":"
  },
  {
    "path": "packages/core/src/index.ts",
    "chars": 64,
    "preview": "export { Transmart } from './transmart'\nexport * from './types'\n"
  },
  {
    "path": "packages/core/src/language.ts",
    "chars": 460,
    "preview": "export function getLanguageDisplayName(code: string) {\n  try {\n    code = code.replace('_', '-') // support chrome.i18n."
  },
  {
    "path": "packages/core/src/limit.ts",
    "chars": 99,
    "preview": "import * as pLimit from 'p-limit'\n\nconst CONCURRENCY = 5\n\nexport const limit = pLimit(CONCURRENCY)\n"
  },
  {
    "path": "packages/core/src/split.ts",
    "chars": 2439,
    "preview": "import { encode } from 'gpt-3-encoder'\n\nexport function splitJSONtoSmallChunks(\n  object: Record<string, unknown>,\n  opt"
  },
  {
    "path": "packages/core/src/task.ts",
    "chars": 3061,
    "preview": "import { Transmart } from './transmart'\nimport { RunWork } from './types'\nimport { readFile } from 'node:fs/promises'\nim"
  },
  {
    "path": "packages/core/src/translate.ts",
    "chars": 3783,
    "preview": "import fetch from 'node-fetch'\nimport { getLanguageDisplayName } from './language'\nimport { TranslateParams } from './ty"
  },
  {
    "path": "packages/core/src/transmart.ts",
    "chars": 6477,
    "preview": "import * as fs from 'fs-extra'\nimport * as path from 'path'\nimport { TransmartOptions, RunOptions, RunWork, TransmartSta"
  },
  {
    "path": "packages/core/src/types.ts",
    "chars": 3821,
    "preview": "export interface TransmartOptions {\n  /**\n   * the language that Transmart will use as a reference to translate other ta"
  },
  {
    "path": "packages/core/src/util.ts",
    "chars": 641,
    "preview": "import { createHash } from 'node:crypto'\nimport { readFileSync } from 'node:fs'\nimport * as path from 'path'\n\n/**\n * A f"
  },
  {
    "path": "packages/core/test/locales/de/common.json",
    "chars": 1345,
    "preview": "{\n  \"create_app\": \"Anwendung erstellen\",\n  \"slogan_title\": \"Erstellen Sie ChatGPT-Anwendungen in Sekunden\",\n  \"site_desc"
  },
  {
    "path": "packages/core/test/locales/de/tos.json",
    "chars": 227,
    "preview": "{\n  \"title\": \"Nutzungsbedingungen für Open Assistant\",\n  \"content\": \"Um Open Assistant weiterhin nutzen zu können, müsse"
  },
  {
    "path": "packages/core/test/locales/en/common.json",
    "chars": 1245,
    "preview": "{\n  \"create_app\": \"Create Application\",\n  \"slogan_title\": \"Create ChatGPT Application in seconds\",\n  \"site_desc\": \"Insta"
  },
  {
    "path": "packages/core/test/locales/en/large-file.json",
    "chars": 156599,
    "preview": "{\n  \"default_template_anchor\": {\n    \"message\": \"Anchor\",\n    \"description\": \"Title of the Anchor template.\"\n  },\n  \"def"
  },
  {
    "path": "packages/core/test/locales/en/tos.json",
    "chars": 196,
    "preview": "{\n  \"title\": \"Terms of Service for Open Assistant\",\n  \"content\": \"To continue using Open Assistant, you have to accept o"
  },
  {
    "path": "packages/core/test/locales/jp/common.json",
    "chars": 935,
    "preview": "{\n  \"create_app\": \"アプリケーションを作成する\",\n  \"slogan_title\": \"数秒でChatGPTアプリケーションを作成する\",\n  \"site_desc\": \"ChatGPTアプリケーションを即座に使用するか"
  },
  {
    "path": "packages/core/test/locales/zh-CN/common.json",
    "chars": 805,
    "preview": "{\n  \"create_app\": \"Create my Application\",\n  \"slogan_title\": \"在几秒钟内创建 ChatGPT 应用程序\",\n  \"site_desc\": \"即刻使用各种 ChatGPT 应用程序"
  },
  {
    "path": "packages/core/test/locales/zh-CN/large-file.json",
    "chars": 113257,
    "preview": "{\n  \"default_template_anchor\": {\n    \"message\": \"锚点\",\n    \"description\": \"锚点模板的标题。\"\n  },\n  \"default_template_bbcode\": {\n"
  },
  {
    "path": "packages/core/test/locales/zh-CN/tos.json",
    "chars": 128,
    "preview": "{\n  \"title\": \"Open Assistant 服务条款\",\n  \"content\": \"在继续使用 Open Assistant 之前,您必须先接受我们的服务条款。\",\n  \"accept\": \"接受\",\n  \"decline\""
  },
  {
    "path": "packages/core/test/locales/zh-TW/common.json",
    "chars": 5398,
    "preview": "{\n  \"default_template_anchor\": {\n    \"message\": \"錨點\",\n    \"description\": \"錨點模板的標題。\"\n  },\n  \"default_template_bbcode\": {\n"
  },
  {
    "path": "packages/core/test/locales/zh-TW/tos.json",
    "chars": 126,
    "preview": "{\n  \"title\": \"Open Assistant 服務條款\",\n  \"content\": \"為了繼續使用 Open Assistant,您必須先接受我們的服務條款。\",\n  \"accept\": \"接受\",\n  \"decline\": "
  },
  {
    "path": "packages/core/tsconfig.build.json",
    "chars": 247,
    "preview": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"module\": \"CommonJS\",\n    \"outDir\""
  },
  {
    "path": "tsconfig.json",
    "chars": 772,
    "preview": "{\n  \"compilerOptions\": {\n    \"module\": \"esnext\",\n    \"useDefineForClassFields\": true,\n    \"target\": \"ESNext\",\n    \"lib\":"
  }
]

About this extraction

This page contains the full source code of the Quilljou/transmart GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 73 files (349.2 KB), approximately 105.6k tokens, and a symbol index with 38 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!