Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ If these doesn't answer your question
* Use [our Slack](https://bit.ly/plyr-chat) if you need help using Plyr or have questions about Plyr.

## Commenting

When commenting, keep a civil tone and stay on topic. Don't ask for [support](#support), or post "+1" or "I agree" type of comments. Use the emojis instead.

Asking for the status on issues is discouraged. Unless someone has explicitly said in an issue that it's work in progress, most likely that means no one is working on it. We have a lot to do, and it may not be a top priority for us.
Expand Down Expand Up @@ -38,3 +39,15 @@ Please follow the instructions in our issue templates. Don't use github issues t
* When finished, push the changes to your GitHub repository and send a pull request to **develop**. Describe what your PR does.

* If the Travis build fails, or if you get a code review with change requests, you can fix these by pushing new or rebased commits to the branch.

## Contributing translations

* Fork Plyr, and create a new branch in your fork, based on the **develop** branch

* Make and translate language file `src/locales/{lang}.js`, where `{lang}` is [IETF BCP 47](https://en.wikipedia.org/wiki/IETF_language_tag) language tag. The language tag should have language and region subtags, seperated by a hyphen. The region subtag should be written in upper case. Other subtags can also be added if needed. Example of valid language tag is `en-GB`. It is recommended to copy and edit English translation.

* Add your language to `src/locales/index.js`. Make sure to import your file and follow the file format. The entry `name` should be native name of language.

* Test your changes.

* When finished, commit and push the changes to your GitHub repository and send a pull request to **develop**.
2 changes: 1 addition & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const paths = {
// Source paths
src: {
sass: path.join(__dirname, 'src/sass/**/*.scss'),
js: path.join(__dirname, 'src/js/**/*.js'),
js: path.join(__dirname, 'src/{js,locales}/**/*.js'),
sprite: path.join(__dirname, 'src/sprite/*.svg'),
},

Expand Down
9 changes: 8 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Plyr is a simple, lightweight, accessible and customizable HTML5, YouTube and Vi
- 📱 **Playsinline** - supports the `playsinline` attribute
- 🏎 **Speed controls** - adjust speed on the fly
- 📖 **Multiple captions** - support for multiple caption tracks
- 🌎 **i18n support** - support for internationalization of controls
- 🌎 **[i18n support](#internationalization)** - support for internationalization of controls
- 👌 **[Preview thumbnails](#preview-thumbnails)** - support for displaying preview thumbnails
- 🤟 **No frameworks** - written in "vanilla" ES6 JavaScript, no jQuery required
- 💁‍♀️ **SASS** - to include in your build processes
Expand Down Expand Up @@ -277,6 +277,7 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
| `debug` | Boolean | `false` | Display debugging information in the console |
| `controls` | Array, Function or Element | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return either an element or HTML string for the controls. Three arguments will be passed to your function; `id` (the unique id for the player), `seektime` (the seektime step in seconds), and `title` (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. |
| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If the default controls are used, you can specify which settings to show in the menu |
| `language` | String | `en` | Language code (IETF BCP 47) for UI internationalization. |
| `i18n` | Object | See [defaults.js](/src/js/config/defaults.js) | Used for internationalization (i18n) of the text within the UI. |
| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. |
| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. |
Expand Down Expand Up @@ -625,6 +626,12 @@ You can see the example VTT files [here](https://cdn.plyr.io/static/demo/thumbs/

Fullscreen in Plyr is supported by all browsers that [currently support it](http://caniuse.com/#feat=fullscreen).

# Internationalization

Internationalization (i18n) language could be specified with `language` option. It will translate all controls in Plyr. If the language is not specified, it will default to English.

If you want custom internationalization values, you should specify them to `i18n` option.

# Browser support

Plyr supports the last 2 versions of most _modern_ browsers.
Expand Down
51 changes: 5 additions & 46 deletions src/js/config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ const defaults = {
// Disable the standard context menu
disableContextMenu: true,

// Language
language: 'en',

// Sprite (for icons)
loadSprite: true,
iconPrefix: 'plyr',
Expand Down Expand Up @@ -142,52 +145,8 @@ const defaults = {
],
settings: ['captions', 'quality', 'speed'],

// Localisation
i18n: {
restart: 'Restart',
rewind: 'Rewind {seektime}s',
play: 'Play',
pause: 'Pause',
fastForward: 'Forward {seektime}s',
seek: 'Seek',
seekLabel: '{currentTime} of {duration}',
played: 'Played',
buffered: 'Buffered',
currentTime: 'Current time',
duration: 'Duration',
volume: 'Volume',
mute: 'Mute',
unmute: 'Unmute',
enableCaptions: 'Enable captions',
disableCaptions: 'Disable captions',
download: 'Download',
enterFullscreen: 'Enter fullscreen',
exitFullscreen: 'Exit fullscreen',
frameTitle: 'Player for {title}',
captions: 'Captions',
settings: 'Settings',
pip: 'PIP',
menuBack: 'Go back to previous menu',
speed: 'Speed',
normal: 'Normal',
quality: 'Quality',
loop: 'Loop',
start: 'Start',
end: 'End',
all: 'All',
reset: 'Reset',
disabled: 'Disabled',
enabled: 'Enabled',
advertisement: 'Ad',
qualityBadge: {
2160: '4K',
1440: 'HD',
1080: 'HD',
720: 'HD',
576: 'SD',
480: 'SD',
},
},
// Custom localisation
i18n: {},

// URLs
urls: {
Expand Down
10 changes: 10 additions & 0 deletions src/js/utils/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import is from './is';
import { getDeep } from './objects';
import { replaceAll } from './strings';
import languages from '../../locales';

// Skip i18n for abbreviations and brand names
const resources = {
Expand All @@ -21,6 +22,15 @@ const i18n = {
return '';
}

const english = languages.filter(e => e.code === 'en');
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From #1269 (review):

Also should we not use a config option for the default? It may not always be 'en'.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default language should be en because it is only for times, when translation doesn't have some translated strings, so like fallback language.

But maybe there could be support to change fallback language.

const locale = languages.filter(e => !is.empty(config.language) && e.code === config.language);

if (!is.empty(locale)) {
config.i18n = Object.assign({}, english[0].i18n, locale[0].i18n, config.i18n);
} else {
config.i18n = Object.assign({}, english[0].i18n, config.i18n);
}

let string = getDeep(config.i18n, key);

if (is.empty(string)) {
Expand Down
52 changes: 52 additions & 0 deletions src/locales/en.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// ==========================================================================
// Plyr English translation
// ==========================================================================

const i18n = {
restart: 'Restart',
rewind: 'Rewind {seektime}s',
play: 'Play',
pause: 'Pause',
fastForward: 'Forward {seektime}s',
seek: 'Seek',
seekLabel: '{currentTime} of {duration}',
played: 'Played',
buffered: 'Buffered',
currentTime: 'Current time',
duration: 'Duration',
volume: 'Volume',
mute: 'Mute',
unmute: 'Unmute',
enableCaptions: 'Enable captions',
disableCaptions: 'Disable captions',
download: 'Download',
enterFullscreen: 'Enter fullscreen',
exitFullscreen: 'Exit fullscreen',
frameTitle: 'Player for {title}',
captions: 'Captions',
settings: 'Settings',
pip: 'PIP',
menuBack: 'Go back to previous menu',
speed: 'Speed',
normal: 'Normal',
quality: 'Quality',
loop: 'Loop',
start: 'Start',
end: 'End',
all: 'All',
reset: 'Reset',
disabled: 'Disabled',
enabled: 'Enabled',
advertisement: 'Ad',
qualityBadge: {
2160: '4K',
1440: 'HD',
1080: 'HD',
720: 'HD',
576: 'SD',
480: 'SD',
},
};

export default i18n;

13 changes: 13 additions & 0 deletions src/locales/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// ==========================================================================
// Plyr supported languages
// ==========================================================================

import en from './en';
import sl from './sl';

const languages = [
{ code: 'en', name: 'English', i18n: en },
{ code: 'sl', name: 'Slovenščina', i18n: sl },
];

export default languages;
52 changes: 52 additions & 0 deletions src/locales/sl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// ==========================================================================
// Plyr Slovenian translation
// ==========================================================================

const i18n = {
restart: 'Ponovno predvajaj',
rewind: 'Nazaj za {seektime} sekund',
play: 'Predvajaj',
pause: 'Zaustavi',
fastForward: 'Naprej za {seektime} sekund',
seek: 'Pojdi',
seekLabel: '{currentTime} od {duration}',
played: 'Predvajano',
buffered: 'Predpomnjeno',
currentTime: 'Čas',
duration: 'Dolžina',
volume: 'Glasnost',
mute: 'Izklopi zvok',
unmute: 'Vklopi zvok',
enableCaptions: 'Omogoči podnapise',
disableCaptions: 'Onemogoči podnapise',
download: 'Prenesi',
enterFullscreen: 'Odpri celozaslonski način',
exitFullscreen: 'Zapri celozaslonski način',
frameTitle: 'Predvajalnik za {title}',
captions: 'Podnapisi',
settings: 'Nastavitve',
pip: 'PIP',
menuBack: 'Pojdi nazaj v prejšnji meni',
speed: 'Hitrost',
normal: 'Običajna',
quality: 'Kakovost',
loop: 'Zanka',
start: 'Začetek',
end: 'Konec',
all: 'Vse',
reset: 'Ponastavi',
disabled: 'Onemogočeni',
enabled: 'Omogočeni',
advertisement: 'Oglas',
qualityBadge: {
2160: '4K',
1440: 'HD',
1080: 'HD',
720: 'HD',
576: 'SD',
480: 'SD',
},
};

export default i18n;