diff --git a/docs/.vuepress/components/CountrySelect.vue b/docs/.vuepress/components/CountrySelect.vue
index 99f5036..6b61752 100644
--- a/docs/.vuepress/components/CountrySelect.vue
+++ b/docs/.vuepress/components/CountrySelect.vue
@@ -12,5 +12,3 @@ export default {
}),
}
-
-
diff --git a/docs/.vuepress/components/TranslationFrench.vue b/docs/.vuepress/components/TranslationFrench.vue
new file mode 100644
index 0000000..fdd279b
--- /dev/null
+++ b/docs/.vuepress/components/TranslationFrench.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/docs/.vuepress/components/TranslationSingleKey.vue b/docs/.vuepress/components/TranslationSingleKey.vue
new file mode 100644
index 0000000..5dda94a
--- /dev/null
+++ b/docs/.vuepress/components/TranslationSingleKey.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/docs/.vuepress/components/TranslationSpanish.vue b/docs/.vuepress/components/TranslationSpanish.vue
new file mode 100644
index 0000000..fe21094
--- /dev/null
+++ b/docs/.vuepress/components/TranslationSpanish.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index ee16a29..0d0b8d7 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -2,6 +2,7 @@ const { description } = require('./config/meta')
const head = require('./config/head')
const plugins = require('./config/plugins')
const themeConfig = require('./config/themeConfig')
+const { resolve } = require('path')
module.exports = {
title: 'Vue Select',
@@ -9,4 +10,7 @@ module.exports = {
head,
plugins,
themeConfig,
+ alias: {
+ 'vue-select': resolve(__dirname, '../../src'),
+ },
}
diff --git a/docs/.vuepress/config/themeConfig.js b/docs/.vuepress/config/themeConfig.js
index 456abcf..edfb36a 100644
--- a/docs/.vuepress/config/themeConfig.js
+++ b/docs/.vuepress/config/themeConfig.js
@@ -37,7 +37,7 @@ module.exports = {
collapsable: false,
children: [
['guide/accessibility', 'WAI-ARIA Spec'],
- ['guide/localization', 'Localization'],
+ ['guide/localization', 'Localization / i18n'],
],
},
{
diff --git a/docs/.vuepress/enhanceApp.js b/docs/.vuepress/enhanceApp.js
index 62f5b3b..333ab67 100644
--- a/docs/.vuepress/enhanceApp.js
+++ b/docs/.vuepress/enhanceApp.js
@@ -1,4 +1,4 @@
-import vSelect from '../../src/components/Select'
+import vSelect from 'vue-select/components/Select'
export default ({ Vue, options, router, siteData }) => {
Vue.component('v-select', vSelect)
diff --git a/docs/guide/localization.md b/docs/guide/localization.md
index 412edb5..c7f3a88 100644
--- a/docs/guide/localization.md
+++ b/docs/guide/localization.md
@@ -1,45 +1,78 @@
+# Translations
+
+There are a number of strings used within the component that can all be translated. Out of the box,
+Vue Select has translations for the following languages/locales that can be found
+in [`src/locales`](https://github.com/sagalbot/vue-select/tree/master/src/locales):
+
+- [English (default)](https://github.com/sagalbot/vue-select/tree/master/src/locales/en.js)
+- [French](https://github.com/sagalbot/vue-select/tree/master/src/locales/fr.js)
+- [Spanish](https://github.com/sagalbot/vue-select/tree/master/src/locales/es.js)
+
+Translations can be set on for each component instance, or globally for all instances in your app.
+Both methods will use the `locale` prop to determine the text to be used throughout the component.
+
+**Locale Prop**
+
+The `locale` prop accepts a function and should return an object of translated strings. The function
+receives the default english translations for the component. This allows you to override the whole
+object, or change just the values you need. The structure of the returned `locale` object is
+described below.
+
+**Locale Object**
+
+The object returned from the locale prop requires specific keys to be set. Below is an example from
+the english locale that ships with Vue Select:
+
+<<< @/../src/locales/en.js
+
+# Examples
+---
+
+## Translate a Single Instance
+
+Translating a single instance of Vue Select can be accomplished by setting the `locale` function to
+return an object with the translations you need. In the example below, we use the french `locale`
+object that ships with Vue Select.
+
+
+<<< @/.vuepress/components/TranslationFrench.vue
+
+**Modifying Specific Text**
+
+You can also use the `locale` prop to override just the text that you'd like to change. In this
+example, the text in the `no-options` slot is updated to say 'No Options found!!'.
+
+
+<<< @/.vuepress/components/TranslationSingleKey.vue
+
+## Translate all Instances
+
+If you'd like to translate the text for **all** Vue Select instances in your app, you can override
+the default prop when registering the component. In the example below, all instances of Vue Select
+will be translated to Spanish.
+
+
+<<< @/.vuepress/components/TranslationSpanish.vue
+
## Right to Left
Vue Select supports RTL using the standard HTML API using the `dir` prop.
-```html
+```vue
+
```
-The `dir` prop accepts the same values as the [HTML spec](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir):
+The `dir` prop accepts the same values as
+the [HTML spec](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir):
- - `rtl`
- - `ltr`
- - `auto`
+- `rtl`
+- `ltr`
+- `auto`
-## Component Text
+## Contributing Languages
-All of the text within the component has been wrapped within [slots](https://vuejs.org/v2/guide/components.html#Content-Distribution-with-Slots) and can be replaced in your app.
-
-### Loading Spinner
-*Slot Definition:*
-```html
-
- Loading...
-
-```
-*Implementation:*
-```html
-
-
-
-```
-
-### No Options Text
-*Slot Definition:*
-```html
-Sorry, no matching options.
-```
-*Implementation:*
-```html
-
- No Options Here!
-
-```
-
-For a full list of component slots, view the [slots API docs](../api/slots.md).
+If you'd like to see Vue Select translated to a new language, submit a PR with a new
+`locale` file in the `src/locales` folder. The file name should match
+the [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for the language, and
+export a `locale` object.
diff --git a/src/components/Select.vue b/src/components/Select.vue
index 7bfc85b..67bea76 100644
--- a/src/components/Select.vue
+++ b/src/components/Select.vue
@@ -64,8 +64,8 @@
:disabled="disabled"
type="button"
class="vs__clear"
- title="Clear Selected"
- aria-label="Clear Selected"
+ :title="i18n.clearButton.title"
+ :aria-label="i18n.clearButton.ariaLabel"
@click="clearSelection"
>
diff --git a/src/locales/en.js b/src/locales/en.js
new file mode 100644
index 0000000..3e1ae42
--- /dev/null
+++ b/src/locales/en.js
@@ -0,0 +1,19 @@
+export const locale = {
+ spinner: {
+ text: 'Loading...',
+ },
+ noOptions: {
+ text: 'Sorry, no matching options.',
+ },
+ search: {
+ ariaLabel: 'Search for options',
+ },
+ deselectButton: {
+ ariaLabel: (label) => `Deselect ${label}`,
+ title: (label) => `Deselect ${label}`,
+ },
+ clearButton: {
+ ariaLabel: 'Clear Selection',
+ title: 'Clear Selection',
+ },
+}
diff --git a/src/locales/es.js b/src/locales/es.js
new file mode 100644
index 0000000..2ad6fe6
--- /dev/null
+++ b/src/locales/es.js
@@ -0,0 +1,19 @@
+export const locale = {
+ spinner: {
+ text: 'Cargando...',
+ },
+ noOptions: {
+ text: 'Lo sentimos, no hay opciones que coincidan.',
+ },
+ search: {
+ ariaLabel: 'Buscar opciones',
+ },
+ deselectButton: {
+ ariaLabel: (label) => `Deseleccionar ${label}`,
+ title: (label) => `Deseleccionar ${label}`,
+ },
+ clearButton: {
+ ariaLabel: 'Eliminar selección',
+ title: 'Eliminar selección',
+ },
+}
diff --git a/src/locales/fr.js b/src/locales/fr.js
new file mode 100644
index 0000000..b3beb21
--- /dev/null
+++ b/src/locales/fr.js
@@ -0,0 +1,19 @@
+export const locale = {
+ spinner: {
+ text: 'Chargement...',
+ },
+ noOptions: {
+ text: 'Désolé, aucune option correspondante.',
+ },
+ search: {
+ ariaLabel: 'Rechercher des options',
+ },
+ deselectButton: {
+ ariaLabel: (label) => `Désélectionner ${label}`,
+ title: (label) => `Désélectionner ${label}`,
+ },
+ clearButton: {
+ ariaLabel: 'Effacer la sélection',
+ title: 'Effacer la sélection',
+ },
+}
diff --git a/src/mixins/i18n.js b/src/mixins/i18n.js
index a6857f1..e2d5122 100644
--- a/src/mixins/i18n.js
+++ b/src/mixins/i18n.js
@@ -1,25 +1,4 @@
-const deselectLabel = (label) => `Deselect ${label}`
-
-export const text = {
- spinner: {
- text: 'Loading...',
- },
- noOptions: {
- text: 'Sorry, no matching options.',
- },
- search: {
- ariaLabel: 'Search for options',
- },
- selectedOption: {},
- deselectButton: {
- ariaLabel: deselectLabel,
- title: deselectLabel,
- },
- clearButton: {
- ariaLabel: 'Clear Selection',
- title: 'Clear Selection',
- },
-}
+import { locale as english } from '../locales/en.js'
/**
* @this VueSelect
@@ -27,18 +6,18 @@ export const text = {
*/
export default {
props: {
- text: {
+ locale: {
type: Function,
/**
* @param text {Object}
- * @return {*}
+ * @return {Object}
*/
default: (text) => text,
},
},
computed: {
i18n() {
- return this.text(text)
+ return this.locale(english)
},
},
}