From 7825c505902b69173d7ad0e1401ce95c4ba0b5b3 Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Thu, 21 May 2026 14:20:31 -0700 Subject: [PATCH 1/8] Add eslint-plugin-vuejs-accessibility dependency to kolibri-format Adds eslint-plugin-vuejs-accessibility v2.5.0 as a dependency of kolibri-format, spreads flat/recommended into eslint.config.mjs (after pluginJestDom, before eslintConfigPrettier), and bumps the kolibri-format version from 2.2.0 to 2.3.0. Co-Authored-By: Claude Sonnet 4.6 --- packages/kolibri-format/eslint.config.mjs | 15 ++++++++++++++ packages/kolibri-format/package.json | 1 + pnpm-lock.yaml | 25 ++++++++++++++++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/kolibri-format/eslint.config.mjs b/packages/kolibri-format/eslint.config.mjs index af6d568a408..55c70cc1b76 100644 --- a/packages/kolibri-format/eslint.config.mjs +++ b/packages/kolibri-format/eslint.config.mjs @@ -7,6 +7,7 @@ import pluginKolibri from 'eslint-plugin-kolibri'; import pluginN from 'eslint-plugin-n'; import pluginSmallImport from 'eslint-plugin-small-import'; import pluginVue from 'eslint-plugin-vue'; +import pluginVueA11y from 'eslint-plugin-vuejs-accessibility'; import globals from 'globals'; const OFF = 0; @@ -18,6 +19,20 @@ export default [ pluginImportX.flatConfigs.errors, pluginImportX.flatConfigs.warnings, pluginJestDom.configs['flat/recommended'], + ...pluginVueA11y.configs['flat/recommended'], + { + rules: { + // Kolibri design-system components that always render accessible text content + // (e.g. via :text prop). The rule cannot see through component boundaries, so + // we declare them here to prevent false positives on headings that wrap these. + 'vuejs-accessibility/heading-has-content': [ + 'error', + { + accessibleChildren: ['KButton', 'KLabeledIcon', 'KRouterLink', 'KTextTruncator'], + }, + ], + }, + }, eslintConfigPrettier, { plugins: { diff --git a/packages/kolibri-format/package.json b/packages/kolibri-format/package.json index 67bfa00b37e..e239992406f 100644 --- a/packages/kolibri-format/package.json +++ b/packages/kolibri-format/package.json @@ -27,6 +27,7 @@ "eslint-plugin-n": "^17.24.0", "eslint-plugin-small-import": "^1.0.0", "eslint-plugin-vue": "^9.33.0", + "eslint-plugin-vuejs-accessibility": "^2.5.0", "fast-glob": "3.3.3", "globals": "^16.0.0", "kolibri-glob": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 525826ba67f..6e52e72bd02 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1394,6 +1394,9 @@ importers: eslint-plugin-vue: specifier: ^9.33.0 version: 9.33.0(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-vuejs-accessibility: + specifier: ^2.5.0 + version: 2.5.0(eslint@9.39.4(jiti@2.6.1))(globals@16.5.0) fast-glob: specifier: 3.3.3 version: 3.3.3 @@ -5491,6 +5494,13 @@ packages: peerDependencies: eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + eslint-plugin-vuejs-accessibility@2.5.0: + resolution: {integrity: sha512-oZ2fL4tS91Cm/ezH3BueNP+FtpbbeS627OSqqgp9/lsN//glmoPcLBT6D53xwGocLtyBybaT99tX4ThBh8+ytA==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + globals: '>= 13.12.1' + eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -11750,16 +11760,16 @@ snapshots: '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/babel__template@7.4.4': dependencies: '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/body-parser@1.19.6': dependencies: @@ -13915,6 +13925,15 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-plugin-vuejs-accessibility@2.5.0(eslint@9.39.4(jiti@2.6.1))(globals@16.5.0): + dependencies: + aria-query: 5.3.2 + eslint: 9.39.4(jiti@2.6.1) + globals: 16.5.0 + vue-eslint-parser: 9.4.3(eslint@9.39.4(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + eslint-scope@5.1.1: dependencies: esrecurse: 4.3.0 From b7d9fe4fcb65e7c856533bc442594df63f09b57d Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Thu, 21 May 2026 14:20:38 -0700 Subject: [PATCH 2/8] Apply pre-existing kolibri-format auto-fixes in kolibri-build Running kolibri-format --write during the a11y remediation pass also fixed pre-existing formatting violations in three kolibri-build files. Committed separately so the a11y diff stays uncluttered. Co-Authored-By: Claude Sonnet 4.6 --- .../__tests__/webpack.config.plugin.spec.js | 2 +- .../src/__tests__/webpackRtlPlugin.spec.js | 51 +++++++++++-------- packages/kolibri-build/src/createCssInsert.js | 2 +- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/kolibri-build/src/__tests__/webpack.config.plugin.spec.js b/packages/kolibri-build/src/__tests__/webpack.config.plugin.spec.js index 6e1847b0de6..e883542a735 100644 --- a/packages/kolibri-build/src/__tests__/webpack.config.plugin.spec.js +++ b/packages/kolibri-build/src/__tests__/webpack.config.plugin.spec.js @@ -1,4 +1,4 @@ -const path = require('path'); +const path = require('node:path'); const _ = require('lodash'); const webpackConfigPlugin = require('../webpack.config.plugin'); diff --git a/packages/kolibri-build/src/__tests__/webpackRtlPlugin.spec.js b/packages/kolibri-build/src/__tests__/webpackRtlPlugin.spec.js index ae860a43ec7..e671e86d218 100644 --- a/packages/kolibri-build/src/__tests__/webpackRtlPlugin.spec.js +++ b/packages/kolibri-build/src/__tests__/webpackRtlPlugin.spec.js @@ -1,15 +1,15 @@ -const path = require('path'); +const path = require('node:path'); +const fs = require('node:fs'); +const os = require('node:os'); const webpack = require('webpack'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const WebpackRTLPlugin = require('../webpackRtlPlugin'); const { createCssInsert } = require('../createCssInsert'); -const fs = require('fs'); -const os = require('os'); // Polyfill setImmediate for Jest environment (webpack requires it) if (typeof setImmediate === 'undefined') { global.setImmediate = (fn, ...args) => setTimeout(fn, 0, ...args); - global.clearImmediate = (id) => clearTimeout(id); + global.clearImmediate = id => clearTimeout(id); } /** @@ -70,7 +70,9 @@ describe('WebpackRTLPlugin', () => { entry: entryFile, output: { path: outputDir, filename: 'bundle.js' }, module: { - rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }], + rules: [ + { test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }, + ], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css' }), @@ -79,8 +81,8 @@ describe('WebpackRTLPlugin', () => { }); const files = fs.readdirSync(outputDir); - const cssFiles = files.filter((f) => f.endsWith('.css') && !f.endsWith('.rtl.css')); - const rtlCssFiles = files.filter((f) => f.endsWith('.rtl.css')); + const cssFiles = files.filter(f => f.endsWith('.css') && !f.endsWith('.rtl.css')); + const rtlCssFiles = files.filter(f => f.endsWith('.rtl.css')); expect(cssFiles.length).toBeGreaterThan(0); expect(rtlCssFiles.length).toBeGreaterThan(0); @@ -107,7 +109,9 @@ describe('WebpackRTLPlugin', () => { entry: entryFile, output: { path: outputDir, filename: 'bundle.js' }, module: { - rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }], + rules: [ + { test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }, + ], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css' }), @@ -115,7 +119,7 @@ describe('WebpackRTLPlugin', () => { ], }); - compiler.hooks.compilation.tap('TestPlugin', (compilation) => { + compiler.hooks.compilation.tap('TestPlugin', compilation => { compilation.hooks.afterProcessAssets.tap('TestPlugin', () => { for (const chunk of compilation.chunks) { const runtimeModules = [...compilation.chunkGraph.getChunkRuntimeModulesInOrder(chunk)]; @@ -164,7 +168,9 @@ describe('WebpackRTLPlugin', () => { entry: entryFile, output: { path: outputDir, filename: 'bundle.js' }, module: { - rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }], + rules: [ + { test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }, + ], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css' }), @@ -216,7 +222,9 @@ describe('WebpackRTLPlugin', () => { entry: entryFile, output: { path: outputDir, filename: 'bundle.js' }, module: { - rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }], + rules: [ + { test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }, + ], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css' }), @@ -255,7 +263,7 @@ describe('WebpackRTLPlugin', () => { fs.writeFileSync(entryFile, `import('./asyncModule.js');`); }); - it('should generate RTL CSS files', (done) => { + it('should generate RTL CSS files', done => { const outputDir = path.join(tempDir, 'dist2'); const compiler = webpack({ @@ -294,16 +302,16 @@ describe('WebpackRTLPlugin', () => { // Verify that both LTR and RTL CSS files were generated const files = fs.readdirSync(outputDir); // With dynamic imports, CSS ends up in a chunk file not main.css - const cssFiles = files.filter((f) => f.endsWith('.css')); - const rtlCssFiles = cssFiles.filter((f) => f.endsWith('.rtl.css')); - const ltrCssFiles = cssFiles.filter((f) => !f.endsWith('.rtl.css')); + const cssFiles = files.filter(f => f.endsWith('.css')); + const rtlCssFiles = cssFiles.filter(f => f.endsWith('.rtl.css')); + const ltrCssFiles = cssFiles.filter(f => !f.endsWith('.rtl.css')); expect(ltrCssFiles.length).toBeGreaterThan(0); expect(rtlCssFiles.length).toBeGreaterThan(0); done(); }); }); - it('should have miniCssF intercept code in the generated bundle', (done) => { + it('should have miniCssF intercept code in the generated bundle', done => { const outputDir = path.join(tempDir, 'dist3'); const compiler = webpack({ @@ -340,10 +348,7 @@ describe('WebpackRTLPlugin', () => { } // Read the generated bundle and verify the intercept pattern - const bundleContent = fs.readFileSync( - path.join(outputDir, 'bundle.js'), - 'utf-8' - ); + const bundleContent = fs.readFileSync(path.join(outputDir, 'bundle.js'), 'utf-8'); // The bundle should contain the miniCssF definition (from MiniCssExtractPlugin) expect(bundleContent).toContain('miniCssF'); @@ -387,7 +392,7 @@ describe('WebpackRTLPlugin', () => { insert(linkElement); - expect(linkElement.getAttribute('data-webpack-bundle')).toBe('my-bundle-id'); + expect(linkElement).toHaveAttribute('data-webpack-bundle', 'my-bundle-id'); expect(document.head.contains(linkElement)).toBe(true); // Clean up @@ -408,7 +413,9 @@ describe('WebpackRTLPlugin', () => { entry: entryFile, output: { path: outputDir, filename: 'bundle.js' }, module: { - rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }], + rules: [ + { test: /\.css$/, use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')] }, + ], }, plugins: [ new MiniCssExtractPlugin({ diff --git a/packages/kolibri-build/src/createCssInsert.js b/packages/kolibri-build/src/createCssInsert.js index ada12059673..1338f3dd903 100644 --- a/packages/kolibri-build/src/createCssInsert.js +++ b/packages/kolibri-build/src/createCssInsert.js @@ -11,7 +11,7 @@ function createCssInsert(bundleId) { return new Function( 'linkTag', `linkTag.setAttribute("data-webpack-bundle", ${JSON.stringify(bundleId)}); - document.head.appendChild(linkTag);` + document.head.appendChild(linkTag);`, ); } From 0e7bc31b1087377488a9c43dde4d17ecdb6a9f21 Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Thu, 21 May 2026 14:20:44 -0700 Subject: [PATCH 3/8] Fix vuejs-accessibility/alt-text violations: add alt attributes to img elements Co-Authored-By: Claude Sonnet 4.6 --- .../frontend/views/CoachPrompts/index.vue | 91 ++++++++++++++++--- .../ChannelPanel/ChannelDetails.vue | 1 + .../ChannelContentsSummary.vue | 1 + .../views/TopicsPage/TopicsMobileHeader.vue | 1 + .../views/SlideshowRendererComponent.vue | 1 + .../kolibri/components/error/AppError.vue | 5 +- 6 files changed, 86 insertions(+), 14 deletions(-) diff --git a/kolibri/plugins/coach/frontend/views/CoachPrompts/index.vue b/kolibri/plugins/coach/frontend/views/CoachPrompts/index.vue index 18e143ee77f..e1513102c29 100644 --- a/kolibri/plugins/coach/frontend/views/CoachPrompts/index.vue +++ b/kolibri/plugins/coach/frontend/views/CoachPrompts/index.vue @@ -122,14 +122,24 @@

Station 1

Kolibri learning

- + + +

Station 2

Guided practice

- + + + @@ -146,21 +156,36 @@

Station 1

Kolibri learning

- + + +

Station 2

Guided practice

- + + +

Station 3

Independent activity

- + + + @@ -364,14 +389,24 @@

Option 1

Next to each other

- + + +

Option 2

In a triangle

- + + + @@ -400,28 +435,48 @@

Option 1

In a square

- + + +

Option 2

In a rectangle

- + + +

Option 2

In a circle

- + + +

Option 2

In a horseshoe

- + + + @@ -448,14 +503,24 @@

Option 2

In a circle

- + + +

Option 2

In a horseshoe

- + + + diff --git a/kolibri/plugins/device/frontend/views/ManageContentPage/ChannelPanel/ChannelDetails.vue b/kolibri/plugins/device/frontend/views/ManageContentPage/ChannelPanel/ChannelDetails.vue index b9cdea7a650..ab19cabae49 100644 --- a/kolibri/plugins/device/frontend/views/ManageContentPage/ChannelPanel/ChannelDetails.vue +++ b/kolibri/plugins/device/frontend/views/ManageContentPage/ChannelPanel/ChannelDetails.vue @@ -10,6 +10,7 @@ v-if="channel.thumbnail" class="thumbnail" :src="channel.thumbnail" + alt="" loading="lazy" >
diff --git a/kolibri/plugins/learn/frontend/views/TopicsPage/TopicsMobileHeader.vue b/kolibri/plugins/learn/frontend/views/TopicsPage/TopicsMobileHeader.vue index 9370384d69b..2731637e1de 100644 --- a/kolibri/plugins/learn/frontend/views/TopicsPage/TopicsMobileHeader.vue +++ b/kolibri/plugins/learn/frontend/views/TopicsPage/TopicsMobileHeader.vue @@ -19,6 +19,7 @@ diff --git a/kolibri/plugins/slideshow_viewer/frontend/views/SlideshowRendererComponent.vue b/kolibri/plugins/slideshow_viewer/frontend/views/SlideshowRendererComponent.vue index 3c57ba9d7df..d0a3ea31b67 100644 --- a/kolibri/plugins/slideshow_viewer/frontend/views/SlideshowRendererComponent.vue +++ b/kolibri/plugins/slideshow_viewer/frontend/views/SlideshowRendererComponent.vue @@ -45,6 +45,7 @@ > diff --git a/packages/kolibri/components/error/AppError.vue b/packages/kolibri/components/error/AppError.vue index ecb0377a1d5..468d0d9ccb5 100644 --- a/packages/kolibri/components/error/AppError.vue +++ b/packages/kolibri/components/error/AppError.vue @@ -4,7 +4,10 @@ role="alert" class="app-error" > - +

{{ headerText }} From a7ee691bbc70b9da6f8c33b7acffa40337415e20 Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Thu, 21 May 2026 14:21:01 -0700 Subject: [PATCH 4/8] Fix SafeHtmlImage and Lightbox accessibility: keyboard navigation and focus management Co-Authored-By: Claude Sonnet 4.6 --- .../components/SafeHTML/Lightbox.vue | 120 +++++++++--------- .../components/SafeHTML/SafeHtmlImage.vue | 24 +++- .../SafeHTML/__tests__/Lightbox.spec.js | 10 +- 3 files changed, 84 insertions(+), 70 deletions(-) diff --git a/packages/kolibri-common/components/SafeHTML/Lightbox.vue b/packages/kolibri-common/components/SafeHTML/Lightbox.vue index 99def36dc80..018ae7c0e30 100644 --- a/packages/kolibri-common/components/SafeHTML/Lightbox.vue +++ b/packages/kolibri-common/components/SafeHTML/Lightbox.vue @@ -8,65 +8,70 @@ class="lightbox-dialog" data-testid="lightbox-dialog" @close="closeLightbox" - @keydown="onKeyDown" > - -
-
- +
+
+ +
+
+ +
+
+ +
-
- -
-
- -
-
- - - + + + +
@@ -109,10 +114,6 @@ type: String, required: true, }, - alt: { - type: String, - default: '', - }, }, data() { return { @@ -161,6 +162,7 @@ dialogPolyfill.registerDialog(dlg); dlg.showModal(); + this.focusFirstEl(); if (!supportsDialogClosedBy()) { dlg.addEventListener('mousedown', this.onBackdropMouseDown); diff --git a/packages/kolibri-common/components/SafeHTML/SafeHtmlImage.vue b/packages/kolibri-common/components/SafeHTML/SafeHtmlImage.vue index e12cbe5592f..a3eeb8967c2 100644 --- a/packages/kolibri-common/components/SafeHTML/SafeHtmlImage.vue +++ b/packages/kolibri-common/components/SafeHTML/SafeHtmlImage.vue @@ -5,13 +5,18 @@ data-testid="image-container" >
- + +
@@ -90,4 +94,12 @@ max-height: 584px; } + .img-button { + display: block; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + } + diff --git a/packages/kolibri-common/components/SafeHTML/__tests__/Lightbox.spec.js b/packages/kolibri-common/components/SafeHTML/__tests__/Lightbox.spec.js index c32ce8cc19d..01a7f391e28 100644 --- a/packages/kolibri-common/components/SafeHTML/__tests__/Lightbox.spec.js +++ b/packages/kolibri-common/components/SafeHTML/__tests__/Lightbox.spec.js @@ -7,14 +7,12 @@ const { zoomOut$, zoomIn$, closeAction$ } = coreStrings; const sampleOpen = true; const sampleSrc = 'test_img.jpg'; -const sampleAlt = 'Test img alt text'; const renderComponent = () => { return render(Lightbox, { props: { open: sampleOpen, src: sampleSrc, - alt: sampleAlt, }, }); }; @@ -31,13 +29,15 @@ async function clickBtnNTimes(user, btn, times) { } describe('Lightbox', () => { - let user, lightboxDialog, img, zoomOut, zoomIn, close, emitted; + let user, lightboxDialog, img, zoomOut, zoomIn, close, emitted, container; beforeEach(async () => { user = userEvent.setup(); - emitted = renderComponent().emitted; + const result = renderComponent(); + emitted = result.emitted; + container = result.container; lightboxDialog = screen.getByTestId('lightbox-dialog'); - img = screen.getByAltText(sampleAlt); + img = container.querySelector('.expanded-image'); zoomOut = screen.getByLabelText(zoomOut$()); zoomIn = screen.getByLabelText(zoomIn$()); close = screen.getByLabelText(closeAction$()); From a5ee94cae5547f0601bafab1580ab85e673b9f59 Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Thu, 21 May 2026 14:21:18 -0700 Subject: [PATCH 5/8] Fix click, keyboard, and interactive element violations across components Co-Authored-By: Claude Sonnet 4.6 --- .../frontend/views/EpubRendererIndex.vue | 1 + .../frontend/views/CompletionModal/index.vue | 1 + .../frontend/views/SideBar/index.vue | 8 +++++-- .../frontend/views/PerseusRendererIndex.vue | 1 + .../frontend/components/QTISandboxPage.vue | 21 +++++++++++++++++++ .../frontend/views/OnboardingStepBase.vue | 1 + .../components/SidePanelModal/index.vue | 3 ++- .../courses/sidePanel/SidePanelModal.vue | 5 ++++- .../quizzes/QuizReport/AttemptLogList.vue | 16 +++++++++----- .../sortable/DragSortWidget/index.vue | 1 + .../FacilityAdminCredentialsForm.vue | 6 ++++-- packages/kolibri/components/Backdrop.vue | 1 + .../kolibri/components/CoreMenu/index.vue | 5 ++++- .../GlobalSnackbar/internal/CoreSnackbar.vue | 5 ++++- .../pages/AppBarPage/internal/SideNav.vue | 1 + 15 files changed, 63 insertions(+), 13 deletions(-) diff --git a/kolibri/plugins/epub_viewer/frontend/views/EpubRendererIndex.vue b/kolibri/plugins/epub_viewer/frontend/views/EpubRendererIndex.vue index f04ef6c9778..55ff069e5f2 100644 --- a/kolibri/plugins/epub_viewer/frontend/views/EpubRendererIndex.vue +++ b/kolibri/plugins/epub_viewer/frontend/views/EpubRendererIndex.vue @@ -16,6 +16,7 @@

+ +
+ +
+ + diff --git a/kolibri/plugins/facility/frontend/views/users/common/ResetUserPasswordModal.vue b/kolibri/plugins/facility/frontend/views/users/common/ResetUserPasswordModal.vue index f29ff742759..a9ebbb57407 100644 --- a/kolibri/plugins/facility/frontend/views/users/common/ResetUserPasswordModal.vue +++ b/kolibri/plugins/facility/frontend/views/users/common/ResetUserPasswordModal.vue @@ -13,6 +13,7 @@ {{ $tr('username') }}{{ username }}

+ + diff --git a/kolibri/plugins/facility/frontend/views/users/sidePanels/UserCreate/index.vue b/kolibri/plugins/facility/frontend/views/users/sidePanels/UserCreate/index.vue index bdc12be4cd8..76f85b25c74 100644 --- a/kolibri/plugins/facility/frontend/views/users/sidePanels/UserCreate/index.vue +++ b/kolibri/plugins/facility/frontend/views/users/sidePanels/UserCreate/index.vue @@ -33,6 +33,7 @@ class="form" >
+ + {{ coreString('invalidCredentialsError') }}

+ + {{ coreString('invalidCredentialsError') }}

+ + + + + +

{{ getCommonSyncString('changeLater') }} diff --git a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/DeviceNameForm.vue b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/DeviceNameForm.vue index b21626a07f7..95164c68ddb 100644 --- a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/DeviceNameForm.vue +++ b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/DeviceNameForm.vue @@ -5,6 +5,7 @@ :description="$tr('deviceNameDescription')" @continue="handleContinue" > + + diff --git a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue index 2bfb9af40df..d507d867730 100644 --- a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue +++ b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue @@ -5,6 +5,7 @@ @continue="handleContinue" > + + diff --git a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/GuestAccessForm.vue b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/GuestAccessForm.vue index 0cf441064c3..000a146761a 100644 --- a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/GuestAccessForm.vue +++ b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/GuestAccessForm.vue @@ -10,6 +10,7 @@ @continue="handleContinue" > + +

{{ $tr('changeLater') }} diff --git a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/HowAreYouUsingKolibri.vue b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/HowAreYouUsingKolibri.vue index 9a7d22dd98b..667bfc6af37 100644 --- a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/HowAreYouUsingKolibri.vue +++ b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/HowAreYouUsingKolibri.vue @@ -7,6 +7,7 @@ @continue="handleContinue" > + + diff --git a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/RequirePasswordForLearnersForm.vue b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/RequirePasswordForLearnersForm.vue index 98648eede11..1753406cf1a 100644 --- a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/RequirePasswordForLearnersForm.vue +++ b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/RequirePasswordForLearnersForm.vue @@ -9,6 +9,7 @@ @continue="handleContinue" > + +

{{ getCommonSyncString('changeLater') }} diff --git a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/SetUpLearningFacilityForm.vue b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/SetUpLearningFacilityForm.vue index a42dc3e233c..182e21f2085 100644 --- a/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/SetUpLearningFacilityForm.vue +++ b/kolibri/plugins/setup_wizard/frontend/views/onboarding-forms/SetUpLearningFacilityForm.vue @@ -6,6 +6,7 @@ @continue="handleContinue" > + + + + {{ $tr('needToMakeNewPasswordLabel', { user: username }) }}

+ +
+ +
@@ -88,6 +90,7 @@ {{ $tr('incorrectPasswordError') }} + +
{{ $tr('createAccount') }}
+ + {{ profileString('createAccount') }}

{{ description }}

+ +

{{ mergeAccountUsingAdminAccount }}

+ +

{{ mergeAccountUserInfo }}

+ +
{{ $tr('doNotKnowPassword') }} {{ $tr('mergeAccountUserInfo') }} + + diff --git a/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue b/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue index 2a1d95e3fb9..1760cc590f2 100644 --- a/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue +++ b/kolibri/plugins/user_profile/frontend/views/ProfileEditPage.vue @@ -18,6 +18,7 @@ >

{{ $tr('editProfileHeader') }}

+ + + + diff --git a/packages/kolibri-common/components/syncComponentSet/RegisterFacilityModal.vue b/packages/kolibri-common/components/syncComponentSet/RegisterFacilityModal.vue index 74f30616308..7e9b32a7fcc 100644 --- a/packages/kolibri-common/components/syncComponentSet/RegisterFacilityModal.vue +++ b/packages/kolibri-common/components/syncComponentSet/RegisterFacilityModal.vue @@ -2,6 +2,7 @@

{{ $tr('enterToken') }}

+ + diff --git a/packages/kolibri-common/components/userAccounts/UsernameTextbox.vue b/packages/kolibri-common/components/userAccounts/UsernameTextbox.vue index a05d7247844..21f5830c3f0 100644 --- a/packages/kolibri-common/components/userAccounts/UsernameTextbox.vue +++ b/packages/kolibri-common/components/userAccounts/UsernameTextbox.vue @@ -1,5 +1,6 @@ diff --git a/packages/kolibri/components/FilterTextbox.vue b/packages/kolibri/components/FilterTextbox.vue index 92ce685c74c..19147f6be82 100644 --- a/packages/kolibri/components/FilterTextbox.vue +++ b/packages/kolibri/components/FilterTextbox.vue @@ -8,6 +8,7 @@ + +