Skip to content

Commit 63a9cda

Browse files
authored
feat: support partial i18n in message input (#8837)
1 parent 5c87b19 commit 63a9cda

File tree

4 files changed

+62
-51
lines changed

4 files changed

+62
-51
lines changed

packages/message-input/src/vaadin-message-input-mixin.d.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@
55
*/
66
import type { Constructor } from '@open-wc/dedupe-mixin';
77
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8+
import type { I18nMixinClass } from '@vaadin/component-base/src/i18n-mixin.js';
89

910
export interface MessageInputI18n {
10-
send: string;
11-
message: string;
11+
send?: string;
12+
message?: string;
1213
}
1314

1415
export declare function MessageInputMixin<T extends Constructor<HTMLElement>>(
1516
base: T,
16-
): Constructor<ControllerMixinClass> & Constructor<MessageInputMixinClass> & T;
17+
): Constructor<ControllerMixinClass> &
18+
Constructor<I18nMixinClass<MessageInputI18n>> &
19+
Constructor<MessageInputMixinClass> &
20+
T;
1721

1822
export declare class MessageInputMixinClass {
1923
/**
@@ -22,12 +26,11 @@ export declare class MessageInputMixinClass {
2226
value: string | null | undefined;
2327

2428
/**
25-
* The object used to localize this component.
26-
* For changing the default localization, change the entire
27-
* `i18n` object.
29+
* The object used to localize this component. To change the default
30+
* localization, replace this with an object that provides all properties, or
31+
* just the individual properties you want to change.
2832
*
2933
* The object has the following JSON structure and default values:
30-
*
3134
* ```
3235
* {
3336
* // Used as the button label

packages/message-input/src/vaadin-message-input-mixin.js

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@
44
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55
*/
66
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
7+
import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
78
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
89
import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
910

11+
const DEFAULT_I18N = {
12+
send: 'Send',
13+
message: 'Message',
14+
};
15+
1016
/**
1117
* @polymerMixin
1218
* @mixes ControllerMixin
1319
*/
1420
export const MessageInputMixin = (superClass) =>
15-
class MessageInputMixinClass extends ControllerMixin(superClass) {
21+
class MessageInputMixinClass extends I18nMixin(DEFAULT_I18N, ControllerMixin(superClass)) {
1622
static get properties() {
1723
return {
1824
/**
@@ -24,35 +30,6 @@ export const MessageInputMixin = (superClass) =>
2430
sync: true,
2531
},
2632

27-
/**
28-
* The object used to localize this component.
29-
* For changing the default localization, change the entire
30-
* `i18n` object.
31-
*
32-
* The object has the following JSON structure and default values:
33-
*
34-
* ```
35-
* {
36-
* // Used as the button label
37-
* send: 'Send',
38-
*
39-
* // Used as the input field's placeholder and aria-label
40-
* message: 'Message'
41-
* }
42-
* ```
43-
*
44-
* @type {!MessageInputI18n}
45-
* @default {English}
46-
*/
47-
i18n: {
48-
type: Object,
49-
sync: true,
50-
value: () => ({
51-
send: 'Send',
52-
message: 'Message',
53-
}),
54-
},
55-
5633
/**
5734
* Set to true to disable this element.
5835
* @type {boolean}
@@ -80,11 +57,36 @@ export const MessageInputMixin = (superClass) =>
8057

8158
static get observers() {
8259
return [
83-
'__buttonPropsChanged(_button, disabled, i18n)',
84-
'__textAreaPropsChanged(_textArea, disabled, i18n, value)',
60+
'__buttonPropsChanged(_button, disabled, __effectiveI18n)',
61+
'__textAreaPropsChanged(_textArea, disabled, __effectiveI18n, value)',
8562
];
8663
}
8764

65+
/**
66+
* The object used to localize this component. To change the default
67+
* localization, replace this with an object that provides all properties, or
68+
* just the individual properties you want to change.
69+
*
70+
* The object has the following JSON structure and default values:
71+
* ```
72+
* {
73+
* // Used as the button label
74+
* send: 'Send',
75+
*
76+
* // Used as the input field's placeholder and aria-label
77+
* message: 'Message'
78+
* }
79+
* ```
80+
* @return {!MessageInputI18n}
81+
*/
82+
get i18n() {
83+
return super.i18n;
84+
}
85+
86+
set i18n(value) {
87+
super.i18n = value;
88+
}
89+
8890
/** @protected */
8991
ready() {
9092
super.ready();
@@ -134,20 +136,20 @@ export const MessageInputMixin = (superClass) =>
134136
}
135137

136138
/** @private */
137-
__buttonPropsChanged(button, disabled, i18n) {
139+
__buttonPropsChanged(button, disabled, effectiveI18n) {
138140
if (button) {
139141
button.disabled = disabled;
140-
button.textContent = i18n.send;
142+
button.textContent = effectiveI18n.send;
141143
}
142144
}
143145

144146
/** @private */
145-
__textAreaPropsChanged(textArea, disabled, i18n, value) {
147+
__textAreaPropsChanged(textArea, disabled, effectiveI18n, value) {
146148
if (textArea) {
147149
textArea.disabled = disabled;
148150
textArea.value = value;
149151

150-
const message = i18n.message;
152+
const message = effectiveI18n.message;
151153
textArea.placeholder = message;
152154
textArea.accessibleName = message;
153155
}

packages/message-input/test/message-input.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,25 +94,25 @@ describe('message-input', () => {
9494

9595
describe('i18n', () => {
9696
it('should translate button text', () => {
97-
messageInput.i18n = { ...messageInput.i18n, send: 'Lähetä' };
97+
messageInput.i18n = { send: 'Lähetä' };
9898
expect(button.innerText).to.be.equal('Lähetä');
9999
});
100100

101101
it('should translate placeholder', () => {
102-
messageInput.i18n = { ...messageInput.i18n, message: 'Viesti' };
102+
messageInput.i18n = { message: 'Viesti' };
103103
expect(textArea.placeholder).to.be.equal('Viesti');
104104
});
105105

106106
it('should translate aria-label', async () => {
107-
messageInput.i18n = { ...messageInput.i18n, message: 'Viesti' };
107+
messageInput.i18n = { message: 'Viesti' };
108108
await nextFrame();
109109
expect(textArea.inputElement.getAttribute('aria-label')).to.be.equal('Viesti');
110110
});
111111

112-
it('should remove aria-label attribute when translation not defined', async () => {
113-
messageInput.i18n = {};
114-
await nextFrame();
115-
expect(textArea.inputElement.hasAttribute('aria-label')).to.equal(false);
112+
it('should support partial i18n', () => {
113+
messageInput.i18n = { send: 'Lähetä' };
114+
expect(button.innerText).to.be.equal('Lähetä');
115+
expect(textArea.placeholder).to.be.equal('Message');
116116
});
117117
});
118118

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import '../../vaadin-message-input.js';
22
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
3-
import type { MessageInputSubmitEvent } from '../../vaadin-message-input.js';
3+
import type { I18nMixinClass } from '@vaadin/component-base/src/i18n-mixin.js';
4+
import type { MessageInputI18n, MessageInputSubmitEvent } from '../../vaadin-message-input.js';
45

56
const assertType = <TExpected>(actual: TExpected) => actual;
67

78
const input = document.createElement('vaadin-message-input');
89

910
assertType<ControllerMixinClass>(input);
11+
assertType<I18nMixinClass<MessageInputI18n>>(input);
1012

1113
input.addEventListener('submit', (event) => {
1214
assertType<MessageInputSubmitEvent>(event);
1315
assertType<string>(event.detail.value);
1416
});
17+
18+
// I18n
19+
assertType<MessageInputI18n>({});
20+
assertType<MessageInputI18n>({ message: 'message' });

0 commit comments

Comments
 (0)