国际化
介绍
本示例主要展示了国际化模块的相关功能,使用@ohos.i18n接口,实现简单日历展示、字符类型判断、文本断点处理功能;
效果预览
使用说明
- 在主界面,可以点击日历、字符文本处理按钮进入对应功能界面;
- 在日历界面,点击“<” “>”按钮,可以查看上/下月公历信息;
- 在字符、文本处理界面,上方输入框输入一个字符,点击字符类型判断可以查看当前输入的字符类型,下方输入框输入长文本,点击文本断点可以查看文本断点结果,断点处用红色/标记;
具体实现
- 日历功能使用@ohos.i18n模块中Calendar实现,全部逻辑处于Calendar,源码参考:[Calendar.ets]。
/*
* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { i18n } from '@kit.LocalizationKit';
import TitleBar from '../component/TitleBar';
const WEEK_TITLE = [$r('app.string.monday'), $r('app.string.tuesday'), $r('app.string.wednesday'),
$r('app.string.thursday'), $r('app.string.friday'), $r('app.string.saturday'),
$r('app.string.sunday')];
interface Day {
isCurrentMonth: boolean,
isToday: boolean,
date: number
};
@Entry
@Component
struct CalendarView {
@State currentYear: number = 0;
@State @Watch('refreshData') currentMonth: number = 0;
@State daysData: Day[] = [];
private calendar = i18n.getCalendar('en-US');
private toDayY: number = this.calendar.get('year');
private toDayM: number = this.calendar.get('month');
private toDayD: number = this.calendar.get('date');
refreshData() {
this.daysData = [];
this.calendar.set(this.currentYear, this.currentMonth, 1);
let currentMonthStartWeek = this.calendar.get('day_of_week');
let currentMonthJulianDay = this.calendar.get('julian_day');
let preYear = this.currentMonth - 1 >= 0 ? this.currentYear : this.currentYear - 1;
let preMonth = this.currentMonth - 1 >= 0 ? this.currentMonth - 1 : 11;
this.calendar.set(preYear, preMonth, 1);
let preMonthJulianDay = this.calendar.get('julian_day');
let nextYear = this.currentMonth + 1 < 12 ? this.currentYear : this.currentYear + 1;
let nextMonth = this.currentMonth + 1 < 12 ? this.currentMonth + 1 : 0;
this.calendar.set(nextYear, nextMonth, 1);
let nextMonthJulianDay = this.calendar.get('julian_day');
let preMonthDays = currentMonthJulianDay - preMonthJulianDay;
let currentMonthDays = nextMonthJulianDay - currentMonthJulianDay;
this.calendar.set(this.currentYear, this.currentMonth, currentMonthDays);
let currentMonthEndWeek = this.calendar.get('day_of_week');
for (let index = preMonthDays - ((currentMonthStartWeek + 5) % 7) + 1; index <= preMonthDays; index++) {
this.daysData.push({
isCurrentMonth: false,
isToday: false,
date: index
})
}
for (let index = 1; index <= currentMonthDays; index++) {
this.daysData.push({
isCurrentMonth: true,
isToday: this.toDayY === this.currentYear && this.toDayM === this.currentMonth && index === this.toDayD,
date: index
})
}
for (let index = 1; index <= (8 - currentMonthEndWeek) % 7; index++) {
this.daysData.push({
isCurrentMonth: false,
isToday: false,
date: index
})
}
}
aboutToAppear() {
this.currentYear = this.toDayY;
this.currentMonth = this.toDayM;
this.refreshData();
}
build() {
Column() {
TitleBar({ hasBackPress: true, title: $r('app.string.calendar') })
Title({
currentYear: $currentYear,
currentMonth: $currentMonth,
goToday: () => {
if (this.currentYear === this.toDayY && this.currentMonth === this.toDayM) {
return;
}
this.currentYear = this.toDayY;
this.currentMonth = this.toDayM;
}
})
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(WEEK_TITLE, (item: Resource, index) => {
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
ForEach(this.daysData.slice(index * WEEK_TITLE.length, (index + 1) * WEEK_TITLE.length), (day: Day) => {
Text(`${day.date}`)
.height(24)
.width(24)
.textAlign(TextAlign.Center)
.fontSize(14)
.fontColor(day.isToday ? Color.White : Color.Black)
.backgroundColor(day.isToday ? Color.Blue : '')
.borderRadius(20)
.opacity(day.isCurrentMonth ? 1.0 : 0.2)
})
}
.width('100%')
.margin({ top: 16 })
})
}
.padding({ left: 24, right: 24 })
.width('100%')
}
.backgroundColor(Color.White)
}
}
@Component
struct Title {
@Link currentYear: number;
@Link currentMonth: number;
private goToday: () => void = (): void =>{}
build() {
Column() {
Row() {
Row() {
Image($r('app.media.ic_public_small_left'))
.id('pre_month')
.height(24)
.width(12)
}
.margin({ left: 5 })
.height('100%')
.aspectRatio(1)
.justifyContent(FlexAlign.Center)
.onClick(() => {
this.currentYear = this.currentMonth - 1 >= 0 ? this.currentYear : this.currentYear - 1;
this.currentMonth = this.currentMonth - 1 >= 0 ? this.currentMonth - 1 : 11;
})
Text(`${this.currentYear}-${this.currentMonth + 1 >= 10 ? '' : '0'}${this.currentMonth + 1}`)
.fontSize(16)
.fontColor(Color.Black)
Row() {
Image($r('app.media.ic_public_small_right'))
.id('next_month')
.height(24)
.width(12)
}
.height('100%')
.aspectRatio(1)
.justifyContent(FlexAlign.Center)
.onClick(() => {
this.currentYear = this.currentMonth + 1 < 12 ? this.currentYear : this.currentYear + 1;
this.currentMonth = this.currentMonth + 1 < 12 ? this.currentMonth + 1 : 0;
})
Blank()
Row() {
Text($r('app.string.today'))
.id('today')
.fontColor(Color.Blue)
.fontSize(16)
.padding({ right: 24 })
}
.height('100%')
.aspectRatio(1)
.onClick(() => {
this.goToday()
})
}
.width('100%')
.height(56)
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
ForEach(WEEK_TITLE, (str: Resource) => {
Text(str)
.fontSize(14)
.fontColor(Color.Black)
.opacity(0.5)
.height(24)
.width(24)
.textAlign(TextAlign.Center)
})
}
.width('100%')
.padding({ left: 24, right: 24 })
}
}
}
- 字符类型判断功能使用@ohos.i18n模块中Unicode实现,全部逻辑处于TextProcessing,源码参考:[TextProcessing.ets]。
/*
* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import TitleBar from '../component/TitleBar';
import ResourceUtil from '../util/ResourceUtil';
import { i18n } from '@kit.LocalizationKit';
import { common } from '@kit.AbilityKit';
const types = ['U_UNASSIGNED', 'U_GENERAL_OTHER_TYPES', 'U_UPPERCASE_LETTER',
'U_LOWERCASE_LETTER', 'U_TITLECASE_LETTER', 'U_MODIFIER_LETTER',
'U_OTHER_LETTER', 'U_NON_SPACING_MARK', 'U_ENCLOSING_MARK',
'U_COMBINING_SPACING_MARK', 'U_DECIMAL_DIGIT_NUMBER', 'U_LETTER_NUMBER',
'U_OTHER_NUMBER', 'U_SPACE_SEPARATOR', 'U_LINE_SEPARATOR',
'U_PARAGRAPH_SEPARATOR', 'U_CONTROL_CHAR', 'U_FORMAT_CHAR',
'U_PRIVATE_USE_CHAR', 'U_SURROGATE', 'U_DASH_PUNCTUATION',
'U_START_PUNCTUATION', 'U_END_PUNCTUATION', 'U_CONNECTOR_PUNCTUATION',
'U_OTHER_PUNCTUATION', 'U_MATH_SYMBOL', 'U_CURRENCY_SYMBOL',
'U_MODIFIER_SYMBOL', 'U_OTHER_SYMBOL', 'U_INITIAL_PUNCTUATION',
'U_FINAL_PUNCTUATION', 'U_CHAR_CATEGORY_COUNT'];
const LOCALE = i18n.System.getSystemLocale();
const TAG = 'TextProcessing';
const MAX = 60;
@Entry
@Component
struct TextProcessing {
@State textTypeResult: string = '';
@State textTypeValue: string = '';
@State areaTextValue: string = '';
@State areaTextResult: string[] = [];
@State textTypes: Array<string> = [];
private breakIterator = i18n.getLineInstance(LOCALE);
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
async aboutToAppear() {
this.textTypes = await ResourceUtil.getStringArray($r('app.strarray.text_type_arr').id, this.context);
}
build() {
Column() {
TitleBar({ hasBackPress: true, title: $r('app.string.text_processing') })
Text($r('app.string.character_type_detection'))
.padding({ top: 22, left: 24 })
.width('100%')
Column() {
TextInput({ placeholder: $r('app.string.character_type_tip') })
.id('short_text_input')
.maxLength(1)
.placeholderFont({ size: 16 })
.backgroundColor(Color.Transparent)
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height(50)
.onChange((value) => {
this.textTypeValue = value;
})
Divider()
.strokeWidth(1)
.opacity(0.05)
.margin({ left: 12, right: 12 })
.backgroundColor(Color.Black)
Text(this.textTypeResult)
.width('100%')
.textAlign(TextAlign.Start)
.padding({ top: 12, left: 12 })
.fontColor(Color.Black)
.opacity(0.9)
.fontSize(16)
}
.backgroundColor(Color.White)
.margin({ left: 12, right: 12, top: 8 })
.border({ radius: 16 })
.height(106)
Button($r('app.string.show_character_type'))
.id('show_character_type')
.width(180)
.height(36)
.margin({ top: 12 })
.onClick(() => {
if (!this.textTypeValue) {
this.textTypeResult = ''
return;
}
let type = i18n.Unicode.getType(this.textTypeValue);
this.textTypeResult = this.textTypes[types.indexOf(type)];
})
Text($r('app.string.text_break'))
.padding({ top: 22, left: 24 })
.width('100%')
Column() {
Stack({ alignContent: Alignment.BottomEnd }) {
TextArea({ placeholder: $r('app.string.long_piece_of_text') })
.id('long_text_input')
.placeholderFont({ size: 16 })
.backgroundColor(Color.Transparent)
.inputFilter(this.areaTextValue.length < MAX ? '' : '^$')
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height(124)
.onChange((value) => {
this.areaTextValue = value;
})
Text(`${this.areaTextValue.length}`)
.fontSize(16)
.opacity(0.4)
.padding(10)
}
Divider()
.strokeWidth(1)
.opacity(0.05)
.margin({ left: 12, right: 12 })
.backgroundColor(Color.Black)
Text() {
ForEach(this.areaTextResult, (str: string, index) => {
Span(str)
.fontColor(Color.Black)
.fontSize(16)
if (index !== this.areaTextResult.length - 1) {
Span('/')
.fontColor(Color.Red)
.fontSize(16)
}
})
}
.width('100%')
.height(84)
.textAlign(TextAlign.Start)
.padding({ top: 12, left: 12 })
.opacity(0.9)
}
.backgroundColor(Color.White)
.margin({ left: 12, right: 12, top: 8 })
.border({ radius: 16 })
.height(232)
Button($r('app.string.text_breakpoint'))
.width(180)
.height(36)
.margin({ top: 12 })
.onClick(() => {
let tem: string[] = []
this.breakIterator.setLineBreakText(this.areaTextValue);
this.breakIterator.first();
let pos = this.breakIterator.next();
let flag = 0
while (pos !== -1) {
tem.push(this.areaTextValue.slice(flag, pos));
flag = pos;
pos = this.breakIterator.next();
}
this.areaTextResult = tem;
})
}
.height('100%')
.width('100%')
}
}
- 文本断点功能使用@ohos.i18n模块中breakIterator实现,全部逻辑处于TextProcessing,源码参考:[TextProcessing.ets]。
/*
* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import TitleBar from '../component/TitleBar';
import ResourceUtil from '../util/ResourceUtil';
import { i18n } from '@kit.LocalizationKit';
import { common } from '@kit.AbilityKit';
const types = ['U_UNASSIGNED', 'U_GENERAL_OTHER_TYPES', 'U_UPPERCASE_LETTER',
'U_LOWERCASE_LETTER', 'U_TITLECASE_LETTER', 'U_MODIFIER_LETTER',
'U_OTHER_LETTER', 'U_NON_SPACING_MARK', 'U_ENCLOSING_MARK',
'U_COMBINING_SPACING_MARK', 'U_DECIMAL_DIGIT_NUMBER', 'U_LETTER_NUMBER',
'U_OTHER_NUMBER', 'U_SPACE_SEPARATOR', 'U_LINE_SEPARATOR',
'U_PARAGRAPH_SEPARATOR', 'U_CONTROL_CHAR', 'U_FORMAT_CHAR',
'U_PRIVATE_USE_CHAR', 'U_SURROGATE', 'U_DASH_PUNCTUATION',
'U_START_PUNCTUATION', 'U_END_PUNCTUATION', 'U_CONNECTOR_PUNCTUATION',
'U_OTHER_PUNCTUATION', 'U_MATH_SYMBOL', 'U_CURRENCY_SYMBOL',
'U_MODIFIER_SYMBOL', 'U_OTHER_SYMBOL', 'U_INITIAL_PUNCTUATION',
'U_FINAL_PUNCTUATION', 'U_CHAR_CATEGORY_COUNT'];
const LOCALE = i18n.System.getSystemLocale();
const TAG = 'TextProcessing';
const MAX = 60;
@Entry
@Component
struct TextProcessing {
@State textTypeResult: string = '';
@State textTypeValue: string = '';
@State areaTextValue: string = '';
@State areaTextResult: string[] = [];
@State textTypes: Array<string> = [];
private breakIterator = i18n.getLineInstance(LOCALE);
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
async aboutToAppear() {
this.textTypes = await ResourceUtil.getStringArray($r('app.strarray.text_type_arr').id, this.context);
}
build() {
Column() {
TitleBar({ hasBackPress: true, title: $r('app.string.text_processing') })
Text($r('app.string.character_type_detection'))
.padding({ top: 22, left: 24 })
.width('100%')
Column() {
TextInput({ placeholder: $r('app.string.character_type_tip') })
.id('short_text_input')
.maxLength(1)
.placeholderFont({ size: 16 })
.backgroundColor(Color.Transparent)
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height(50)
.onChange((value) => {
this.textTypeValue = value;
})
Divider()
.strokeWidth(1)
.opacity(0.05)
.margin({ left: 12, right: 12 })
.backgroundColor(Color.Black)
Text(this.textTypeResult)
.width('100%')
.textAlign(TextAlign.Start)
.padding({ top: 12, left: 12 })
.fontColor(Color.Black)
.opacity(0.9)
.fontSize(16)
}
.backgroundColor(Color.White)
.margin({ left: 12, right: 12, top: 8 })
.border({ radius: 16 })
.height(106)
Button($r('app.string.show_character_type'))
.id('show_character_type')
.width(180)
.height(36)
.margin({ top: 12 })
.onClick(() => {
if (!this.textTypeValue) {
this.textTypeResult = ''
return;
}
let type = i18n.Unicode.getType(this.textTypeValue);
this.textTypeResult = this.textTypes[types.indexOf(type)];
})
Text($r('app.string.text_break'))
.padding({ top: 22, left: 24 })
.width('100%')
Column() {
Stack({ alignContent: Alignment.BottomEnd }) {
TextArea({ placeholder: $r('app.string.long_piece_of_text') })
.id('long_text_input')
.placeholderFont({ size: 16 })
.backgroundColor(Color.Transparent)
.inputFilter(this.areaTextValue.length < MAX ? '' : '^$')
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height(124)
.onChange((value) => {
this.areaTextValue = value;
})
Text(`${this.areaTextValue.length}`)
.fontSize(16)
.opacity(0.4)
.padding(10)
}
Divider()
.strokeWidth(1)
.opacity(0.05)
.margin({ left: 12, right: 12 })
.backgroundColor(Color.Black)
Text() {
ForEach(this.areaTextResult, (str: string, index) => {
Span(str)
.fontColor(Color.Black)
.fontSize(16)
if (index !== this.areaTextResult.length - 1) {
Span('/')
.fontColor(Color.Red)
.fontSize(16)
}
})
}
.width('100%')
.height(84)
.textAlign(TextAlign.Start)
.padding({ top: 12, left: 12 })
.opacity(0.9)
}
.backgroundColor(Color.White)
.margin({ left: 12, right: 12, top: 8 })
.border({ radius: 16 })
.height(232)
Button($r('app.string.text_breakpoint'))
.width(180)
.height(36)
.margin({ top: 12 })
.onClick(() => {
let tem: string[] = []
this.breakIterator.setLineBreakText(this.areaTextValue);
this.breakIterator.first();
let pos = this.breakIterator.next();
let flag = 0
while (pos !== -1) {
tem.push(this.areaTextValue.slice(flag, pos));
flag = pos;
pos = this.breakIterator.next();
}
this.areaTextResult = tem;
})
}
.height('100%')
.width('100%')
}
}
以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下:
内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
鸿蒙【北向应用开发+南向系统层开发】文档
鸿蒙【基础+实战项目】视频
鸿蒙面经
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!