鸿蒙应用框架开发【国际化】模块功能

国际化

介绍

本示例主要展示了国际化模块的相关功能,使用@ohos.i18n接口,实现简单日历展示、字符类型判断、文本断点处理功能;

效果预览

1

使用说明

  1. 在主界面,可以点击日历、字符文本处理按钮进入对应功能界面;
  2. 在日历界面,点击“<” “>”按钮,可以查看上/下月公历信息;
  3. 在字符、文本处理界面,上方输入框输入一个字符,点击字符类型判断可以查看当前输入的字符类型,下方输入框输入长文本,点击文本断点可以查看文本断点结果,断点处用红色/标记;

具体实现

  1. 日历功能使用@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 })
    }
  }
}
  1. 字符类型判断功能使用@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%')
  }
}
  1. 文本断点功能使用@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%')
  }
}

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

在这里插入图片描述

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值