diff --git a/client/package.json b/client/package.json
index 23e4f22a..62c6a139 100644
--- a/client/package.json
+++ b/client/package.json
@@ -35,6 +35,7 @@
"vue-class-component": "^7.0.2",
"vue-clickaway": "^2.2.2",
"vue-context": "^5.0.0",
+ "vue-i18n": "^8.16.0",
"vue-notification": "^1.3.20",
"vue-property-decorator": "^8.3.0",
"vuex": "^3.1.2"
diff --git a/client/src/components/chat.vue b/client/src/components/chat.vue
index 74d7d51c..0b4e8ebb 100644
--- a/client/src/components/chat.vue
+++ b/client/src/components/chat.vue
@@ -24,7 +24,7 @@
boundariesElement: 'body',
}"
>
- You
+ {{ $t('you') }}
{{ member(message.id).displayname }}
{{ message.content }}
diff --git a/client/src/components/connect.vue b/client/src/components/connect.vue
index a7d3f810..7ae1962c 100644
--- a/client/src/components/connect.vue
+++ b/client/src/components/connect.vue
@@ -6,11 +6,11 @@
n.eko
diff --git a/client/src/components/context.vue b/client/src/components/context.vue
index bdfeae44..07705ce4 100644
--- a/client/src/components/context.vue
+++ b/client/src/components/context.vue
@@ -9,38 +9,40 @@
- Ignore
- Unignore
+ {{ $t('context.ignore') }}
+ {{ $t('context.unignore') }}
- Mute
- Unmute
+ {{ $t('context.mute') }}
+ {{ $t('context.unmute') }}
- Force Release Controls
+ {{ $t('context.release') }}
- Force Take Controls
+ {{ $t('context.take') }}
- Give Controls
+ {{
+ $t('context.give')
+ }}
- Give Controls
+ {{ $t('context.give') }}
- Kick
+ {{ $t('context.kick') }}
- Ban IP
+ {{ $t('context.ban') }}
diff --git a/client/src/components/controls.vue b/client/src/components/controls.vue
index 0797d976..085b04f4 100644
--- a/client/src/components/controls.vue
+++ b/client/src/components/controls.vue
@@ -10,7 +10,7 @@
'request',
]"
v-tooltip="{
- content: !hosted || hosting ? (hosting ? 'Release Controls' : 'Request Controls') : '',
+ content: !hosted || hosting ? (hosting ? $t('controls.release') : $t('controls.request')) : '',
placement: 'top',
offset: 5,
boundariesElement: 'body',
@@ -23,7 +23,7 @@
diff --git a/client/src/components/side.vue b/client/src/components/side.vue
index 6f86ee1a..033ac07e 100644
--- a/client/src/components/side.vue
+++ b/client/src/components/side.vue
@@ -4,11 +4,11 @@
-
- Chat
+ {{ $t('chat') }}
-
- Settings
+ {{ $t('settings') }}
diff --git a/client/src/components/unsupported.vue b/client/src/components/unsupported.vue
index 3f0909a1..5c240c55 100644
--- a/client/src/components/unsupported.vue
+++ b/client/src/components/unsupported.vue
@@ -6,7 +6,7 @@
n.eko
- this browser does not support webrtc
+ {{ $t('unsupported') }}
diff --git a/client/src/locale/en-us.ts b/client/src/locale/en-us.ts
new file mode 100644
index 00000000..8fd05a6d
--- /dev/null
+++ b/client/src/locale/en-us.ts
@@ -0,0 +1,75 @@
+export const chat = 'Chat'
+export const settings = 'Settings'
+export const logout = 'logout'
+export const unsupported = 'this browser does not support webrtc'
+export const admin_loggedin = 'You are logged in as an admin'
+export const you = 'You'
+export const ok = 'ok'
+export const connected = 'connected'
+export const disconnected = 'disconnected'
+
+export const connect = {
+ title: 'Please Login',
+ displayname: 'Display Name',
+ password: 'Password',
+ connect: 'Connect',
+}
+
+export const context = {
+ ignore: 'Ignore',
+ unignore: 'Unignore',
+ mute: 'Mute',
+ unmute: 'Unmute',
+ release: 'Force Release Controls',
+ take: 'Force Take Controls',
+ give: 'Give Controls',
+ kick: 'Kick',
+ ban: 'Ban IP',
+}
+
+export const controls = {
+ release: 'Release Controls',
+ request: 'Request Controls',
+ lock: 'Lock Controls',
+ unlock: 'Unlock Controls',
+}
+
+export const room = {
+ lock: 'Lock Room',
+ unlock: 'Unlock Room',
+ locked: 'Room Locked',
+ unlocked: 'Room Unlocked',
+}
+
+export const setting = {
+ scroll: 'Scroll Sensitivity',
+ scroll_invert: 'Invert Scroll',
+ autoplay: 'Autoplay Video',
+ ignore_emotes: 'Ignore Emotes',
+ chat_sound: 'Play Chat Sound',
+}
+
+export const connection = {
+ success: 'Successfully connected',
+}
+
+export const notifications = {
+ logged_out: '{name} logged out!',
+ controls_taken: '{name} took the controls',
+ controls_taken_force: 'force took the controls',
+ controls_taken_steal: 'took the controls from {name}',
+ controls_released: '{name} released the controls',
+ controls_released_force: 'force released the controls',
+ controls_released_steal: 'released the controls from {name}',
+ controls_given: 'gave the controls to {name}',
+ controls_has: '{name} has the controls',
+ controls_has_alt: 'But I let them know you wanted it',
+ controls_requesting: '{name} is requesting the controls',
+ resolution: 'changed the resolution to {width}x{height}@{rate}',
+ banned: 'banned {name}',
+ kicked: 'kicked {name}',
+ muted: 'muted {name}',
+ unmuted: 'unmuted {name}',
+ room_locked: 'locked the room',
+ room_unlocked: 'unlocked the room',
+}
diff --git a/client/src/locale/index.ts b/client/src/locale/index.ts
new file mode 100644
index 00000000..a72e383a
--- /dev/null
+++ b/client/src/locale/index.ts
@@ -0,0 +1,5 @@
+import * as en from './en-us'
+
+export const messages = {
+ en,
+}
diff --git a/client/src/main.ts b/client/src/main.ts
index fe21c50d..2fc2c243 100644
--- a/client/src/main.ts
+++ b/client/src/main.ts
@@ -10,6 +10,7 @@ import Axios from './plugins/axios'
import Swal from './plugins/swal'
import Anime from './plugins/anime'
+import { i18n } from './plugins/i18n'
import store from './store'
import app from './app.vue'
@@ -24,6 +25,7 @@ Vue.use(Anime)
Vue.use(Client)
new Vue({
+ i18n,
store,
render: h => h(app),
created() {
diff --git a/client/src/neko/index.ts b/client/src/neko/index.ts
index 335eb605..571ab1cf 100644
--- a/client/src/neko/index.ts
+++ b/client/src/neko/index.ts
@@ -54,9 +54,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.disconnect()
this.cleanup()
this.$vue.$swal({
- title: 'You have logged out!',
+ title: this.$vue.$t('notifications.logged_out', { name: 'You' }),
icon: 'info',
- confirmButtonText: 'ok',
+ confirmButtonText: this.$vue.$t('ok') as string,
})
}
@@ -75,7 +75,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$vue.$notify({
group: 'neko',
type: 'success',
- title: 'Successfully connected',
+ title: this.$vue.$t('connection.success') as string,
duration: 5000,
speed: 1000,
})
@@ -86,7 +86,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$vue.$notify({
group: 'neko',
type: 'error',
- title: `Disconnected:`,
+ title: this.$vue.$t('disconnected') as string,
text: reason ? reason.message : undefined,
duration: 5000,
speed: 1000,
@@ -111,10 +111,10 @@ export class NekoClient extends BaseClient implements EventEmitter {
protected [EVENT.SYSTEM.DISCONNECT]({ message }: DisconnectPayload) {
this.onDisconnected(new Error(message))
this.$vue.$swal({
- title: 'Disconnected!',
+ title: this.$vue.$t('disconnected'),
text: message,
icon: 'error',
- confirmButtonText: 'ok',
+ confirmButtonText: this.$vue.$t('ok') as string,
})
}
@@ -125,7 +125,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.user.setMembers(members)
this.$accessor.chat.newMessage({
id: this.id,
- content: 'connected',
+ content: this.$vue.$t('connected') as string,
type: 'event',
created: new Date(),
})
@@ -137,7 +137,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
if (member.id !== this.id) {
this.$accessor.chat.newMessage({
id: member.id,
- content: 'connected',
+ content: this.$vue.$t('connected') as string,
type: 'event',
created: new Date(),
})
@@ -152,7 +152,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id: member.id,
- content: 'disconnected',
+ content: this.$vue.$t('disconnected') as string,
type: 'event',
created: new Date(),
})
@@ -174,7 +174,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$vue.$notify({
group: 'neko',
type: 'info',
- title: `You have the controls`,
+ title: this.$vue.$t('notifications.controls_taken', { name: this.$vue.$t('you') }) as string,
duration: 5000,
speed: 1000,
})
@@ -182,7 +182,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id: member.id,
- content: 'took the controls',
+ content: this.$vue.$t('notifications.controls_taken', { name: '' }) as string,
type: 'event',
created: new Date(),
})
@@ -199,7 +199,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$vue.$notify({
group: 'neko',
type: 'info',
- title: `You released the controls`,
+ title: this.$vue.$t('notifications.controls_released', { name: this.$vue.$t('you') }) as string,
duration: 5000,
speed: 1000,
})
@@ -207,7 +207,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id: member.id,
- content: 'released the controls',
+ content: this.$vue.$t('notifications.controls_released') as string,
type: 'event',
created: new Date(),
})
@@ -222,8 +222,8 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$vue.$notify({
group: 'neko',
type: 'info',
- title: `${member.displayname} has the controls`,
- text: 'But I let them know you wanted it',
+ title: this.$vue.$t('notifications.controls_has', { name: member.displayname }) as string,
+ text: this.$vue.$t('notifications.controls_has_alt') as string,
duration: 5000,
speed: 1000,
})
@@ -238,7 +238,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$vue.$notify({
group: 'neko',
type: 'info',
- title: `${member.displayname} is requesting the controls`,
+ title: this.$vue.$t('notifications.controls_requesting', { name: member.displayname }) as string,
duration: 5000,
speed: 1000,
})
@@ -253,7 +253,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.remote.setHost(member)
this.$accessor.chat.newMessage({
id,
- content: `gave the controls to ${member.id == this.id ? 'you' : member.displayname}`,
+ content: this.$vue.$t('notifications.controls_given', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -310,7 +312,11 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `changed the resolution to ${width}x${height}@${rate}`,
+ content: this.$vue.$t('notifications.resolution', {
+ width: width,
+ height: height,
+ rate: rate,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -331,7 +337,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `banned ${member.id == this.id ? 'you' : member.displayname}`,
+ content: this.$vue.$t('notifications.banned', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -349,7 +357,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `kicked ${member.id == this.id ? 'you' : member.displayname}`,
+ content: this.$vue.$t('notifications.kicked', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -369,7 +379,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `muted ${member.id == this.id ? 'you' : member.displayname}`,
+ content: this.$vue.$t('notifications.muted', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -389,7 +401,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `unmuted ${member.displayname}`,
+ content: this.$vue.$t('notifications.unmuted', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -399,7 +413,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.setLocked(true)
this.$accessor.chat.newMessage({
id,
- content: `locked the room`,
+ content: this.$vue.$t('notifications.room_locked') as string,
type: 'event',
created: new Date(),
})
@@ -409,7 +423,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.setLocked(false)
this.$accessor.chat.newMessage({
id,
- content: `unlocked the room`,
+ content: this.$vue.$t('notifications.room_unlocked') as string,
type: 'event',
created: new Date(),
})
@@ -421,7 +435,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
if (!target) {
this.$accessor.chat.newMessage({
id,
- content: `force took the controls`,
+ content: this.$vue.$t('notifications.controls_taken_force') as string,
type: 'event',
created: new Date(),
})
@@ -435,7 +449,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `took the controls from ${member.id == this.id ? 'you' : member.displayname}`,
+ content: this.$vue.$t('notifications.controls_taken_steal', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -446,7 +462,7 @@ export class NekoClient extends BaseClient implements EventEmitter {
if (!target) {
this.$accessor.chat.newMessage({
id,
- content: `force released the controls`,
+ content: this.$vue.$t('notifications.controls_released_force') as string,
type: 'event',
created: new Date(),
})
@@ -460,7 +476,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `released the controls from ${member.id == this.id ? 'you' : member.displayname}`,
+ content: this.$vue.$t('notifications.controls_released_steal', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
@@ -480,7 +498,9 @@ export class NekoClient extends BaseClient implements EventEmitter {
this.$accessor.chat.newMessage({
id,
- content: `gave the controls to ${member.id == this.id ? 'you' : member.displayname}`,
+ content: this.$vue.$t('notifications.controls_given', {
+ name: member.id == this.id ? this.$vue.$t('you') : member.displayname,
+ }) as string,
type: 'event',
created: new Date(),
})
diff --git a/client/src/plugins/i18n.ts b/client/src/plugins/i18n.ts
new file mode 100644
index 00000000..e5d5b409
--- /dev/null
+++ b/client/src/plugins/i18n.ts
@@ -0,0 +1,10 @@
+import Vue from 'vue'
+import VueI18n from 'vue-i18n'
+import { messages } from '~/locale'
+
+Vue.use(VueI18n)
+
+export const i18n = new VueI18n({
+ locale: 'en',
+ messages,
+})