项目名称
小七翻译
开发背景
这是为了满足自己的日常学习和生活而开发的一个项目。我在学习英语的时候,需要随时用 到英语翻译工具,由于条件限制,手机内存比较小,下载翻译软件浪费内存,感觉线上的翻译工具更加方便,更加符合自己的需求,所以想自己尝试开发一个线上翻译工具,最后选择了微信小程序,完成了小七翻译这个项目。
需求分析
社会的发展,让人们开始对不同国家的语言感兴趣。越来越多的人为了提升自己,也开始去学习和掌握不同的语言。而语言的学习途径很多,但在日常生活中去记忆,去运用无疑是最好的学习方式。在平时的工作,生活中,你会遇到了就在嘴边却记不起来怎么拼写的单词,你会看着各国语言的说明书开始发呆。难道我们要随时都带着厚重的词典?或是每次都要下载翻译软件吗?如果这个时候有一款线上的翻译工具,可以让你随时随地的查看,那将帮你争取到最好的学习时间,也不会占用很多手机内存空间,所以微信小程序成了不错的选择,在此需求上,小七翻译上线。
项目简介
本项目是一款小程序翻译工具。 支持中,英,日,韩,法,西班牙,阿拉伯,泰,希腊,瑞典,保加利亚等等多国国家语言的互翻。具备客服服务功能,可以及时收到用户反馈并解答用户的问题。该工具还能保存用户翻译记录以便以后查看,并且可以回溯10条历史记录到主页中。
项目使用/预览方式
可通过微信搜索 小七翻译进行预览和使用(由于小程序码会被当做广告,这里不提供小程序码)
功能界面预览
详细设计
代码列表
页面实现
pages
pages文件下是四个页面,分别是index,change,history,button。每一项都对应一个页面的路径+文件名信息。文件名不需要写文件后缀,框架会自动去寻找.json,.js.wxml,.wxss四个文件进行处理,数组的第一项代表小程序的初始页面。小程序新增/减少页面,都需要对pages数组进行修改。
window
用于设置小程序的状态栏,导航条,窗口背景颜色
tabBar
小程序若是多tab应用,也就是说可以通过导航栏切换不同的页面,通过tabBar配置指定tab栏的表现形式,和切换时显示的界面。
utils文件下是一些配置文件和,全局样式,和路由。四个页面的公共样式都写在app.wxss中。wxss相当于写css,代码就不做展示。 app.json是界面配置,代码如下
{
"pages": [
"pages/index/index",
"pages/change/change",
"pages/history/history",
"pages/button/button"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#1c1b21",
"navigationBarTitleText": "小七翻译",
"navigationBarTextStyle": "white",
"backgroundColor": "#333"
},
"tabBar": {
"borderStyle": "white",
"position": "top",
"color": "#595959",
"selectedColor": "#1c1b21",
"list": [
{
"pagePath": "pages/index/index",
"text": "翻译"
},
{
"pagePath": "pages/history/history",
"text": "历史"
},
{
"pagePath": "pages/button/button",
"text": "客服中心"
}
]
},
"sitemapLocation": "sitemap.json"
}
index主页面实现
主界面区域划分
index页面有,index.wxml和index.wxss和,index.js组成。微信小程序的动态数据均来自index.js中对应的data。
index.wxml
<!--index.wxml-->
<view class="container">
<view class="change">
<navigator url="/pages/change/change" hover-class="navigator-hover">
<block>
<text>到{{curLang.chs}}</text>
<text class="iconfont icon-down"></text>
</block>
</navigator>
</view>
<view class="input-area">
<text class="iconfont icon-close" hidden="{{hideClearIcon}}" bindtap='onTapClose'></text>
<view class="textarea-wrap">
<textarea placeholder='请输入要翻译的文本' placeholder-style='color: #8995a1' bindinput='onInput' bindconfirm='onConfirm' bindblur='onConfirm' value="{{query}}"></textarea>
</view>
<view class="text-area">
<view class="text-title">译文</view>
<view class="text-result" wx:for="{{result}}" wx:key="index">
<text selectable="true">{{item.dst}}</text>
</view>
</view>
</view>
<view class="copyright">
<text>© 2020 小雍嘤版权所有</text>
</view>
</view>
index.js
page()
在js文件中,Page(Object)函数用来注册一个页面。接受一个Object类型参数,其指定页面的初始数据,生命周期回调,事件处理函数等。
data:
data 是页面第一次渲染使用的初始数据。 将会以JSON字符串的形式由逻辑层传至渲染层,因此data中的数据必须是可以转成JSON的类型:字符串,数字,布尔值,对象,数组。 渲染层可以通过 WXML 对数据进行绑定。
onLoad:
onLoad(Object query) 页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
onShow:
onShow() 页面显示/切入前台时触发。
Page.prototype.setData(Object data, Function callback)
setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)Object 以 key: value 的形式表示,将 this.data 中的 key 对应的值改变成 value。其中 key 可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 array[2].message,a.b.c.d,并且不需要在 this.data 中预先定义。
注意
1、 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
2、 仅支持设置可 JSON 化的数据。
3、 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
4、 请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题
onInput onTapClose onConfirm
这三个key都是WXML 中bindinput、bindtap、bindconfir/bindblur的值,然后在js中进行事件绑定
//index.js
//获取应用实例
import { translate } from '../../utils/api.js'
const app = getApp()
Page({
data: {
query: '',
hideClearIcon: true,
result: [],
curLang: {},
handleContact (e) {
console.log(e.detail.path)
console.log(e.detail.query)
}
},
onLoad: function( options) {
console.log('lonload..')
console.log(options)
if(options.query) {
this.setData({ query: options.query })
}
},
onShow: function () {
if (this.data.curLang.lang !== app.globalData.curLang.lang) {
this.setData({ curLang: app.globalData.curLang })
this.onConfirm()
}
},
onInput: function(e) {
this.setData({'query': e.detail.value})
if(this.data.query.length > 0) {
this.setData({ 'hideClearIcon': false })
}else{
this.setData({ 'hideClearIcon': true })
}
console.log('focus')
},
onTapClose: function() {
this.setData({ query: '', hideClearIcon: true})
},
onConfirm: function() {
if (!this.data.query) return
translate(this.data.query, {from: 'auto', to: this.data.curLang.lang}).then(res=>{
this.setData({'result': res.trans_result})
let history = wx.getStorageSync('history')||[]
history.unshift({ query: this.data.query, result: res.trans_result[0].dst})
history.length = history.length > 10 ? 10 : history.length
wx.setStorageSync('history', history)
})
}
})
小程序中的语法,可以查看小程序开发文档
视图容器用 view
navigator
navigator是页面链接,相当于html中的a标签
hover-class
hover-class指定按下去的样式类。当 hover-class="none" 时,没有点击态效果
数据绑定
数据绑定使用 Mustache 语法(双大括号)将变量包起来
hidden属性
hidden属性,后面值默认为false,在页面中显示出这条代码体现是效果,但在js中可以对hidden属性的默认值进行设置,是否在页面表现效果
bindtap
bindtap在小程序中是代表此容器是可以点击的,在js中对bindtap的值进行操作就可以设置点击后要执行的事件
indinput键盘输入时触发,event.detail = {value, cursor, keyCode},keyCode 为键值,2.1.0 起支持,处理函数可以直接 return 一个字符串,将替换输入框的内容。
bindconfirm点击完成按钮时触发,event.detail = {value: value} bindblur输入框失去焦点时触发,event.detail = {value: value}
textarea多行输入框
textarea多行输入框。该组件是原生组件,使用时请注意相关限制
(1) placeholder输入框为空时占位符,与css相同
(2) placeholder-style指定 placeholder 的样式
wx:for
wx:for在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
icon
当用到icon图标的时候,可以新建一个文件夹,其中放入icon图标的代码文件,在app.wxss中应用,以便于所有文件引用
图标引入
iconfont图标的可以去iconfont网站找。 下面时代码引入方式。
@font-face {font-family: "iconfont";
src: url('https://at.alicdn.com/t/font_780826_5ljr5es53es.ttf') format('truetype')
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-down:before { content: "\e600"; }
.icon-right:before { content: "\e642"; }
.icon-close:before { content: "\e601"; }
.icon-arrow-right:before { content: "\e6b4"; }
.icon-duihao:before { content: "\e633"; }
input-area的功能细节设计
1、实现在输入框中输入内容时,对onInput进行绑定,显示icon,通过设置hideClearIcon的值为false还是true来控制icon
2、在icon显示后,点击icon删除输入内容,对onTapClose进行事件绑定
3、在输入确定内容后对内容进行翻译,对onConfirm进行绑定,准备翻译,对它进行封装
翻译功能的实现
项目使用了百度翻译api实现翻译功能。需要去官网自己申请使用权限,你会得到一个appid和key,
在utils里加了一个api.js具体代码实现如下
return new Promise((resolve, reject) => {
let salt = Date.now()
let sign = md5(`${appid}${q}${salt}${key}`)
wx.request({
url: 'https://fanyi-api.baidu.com/api/trans/vip/translate',
data: {
q,
from,
to,
appid,
salt,
sign
},
success(res) {
if (res.data && res.data.trans_result) {
resolve(res.data)
} else {
reject({ status: 'error', msg: '翻译失败' })
wx.showToast({
title: '翻译失败',
icon: 'none',
duration: 3000
})
}
},
fail() {
reject({ status: 'error', msg: '翻译失败' })
wx.showToast({
title: '网络异常',
icon: 'none',
duration: 3000
})
}
})
})
}
module.exports.translate = translate
用wx.request去请求数据,使用百度翻译api要用md5加密,再utils文件夹添加一个md5.min.js文件
1、 wx.request发起 HTTPS 网络请求.
2、 wx.showToast(Object object)显示消息提示框
3、 一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现。
exports: 通过该属性,可以对外共享本模块的私有变量与函数
在index.js页面中用import引入api.js,这样就完成了index页面的接口问题,要翻译成什么语言,用change页面实现
change页面实现
change页面区域划分
change.wxml
wx:key
wx:key 如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 中的输入内容, 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。
wx:for-item
wx:for-item 可以指定数组当前元素的变量名
wx:if
wx:if在框架中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块
<!--change.wxml-->
<view class="container lang-list">
<view class="title">翻译成</view>
<view class="item" data-chs="{{language.chs}}" data-lang="{{language.lang}}" data-index="{{index}}" wx:for="{{langList}}" wx:key="index" wx:for-item="language" bindtap='onTapItem' hover-class="view-hover">
<view class="item-inner">
<text class="txt">{{language.chs}}</text>
<text class="iconfont icon-duihao" wx:if="{{index===curLang.index}}"></text>
</view>
</view>
</view>
change.js
//logs.js
const util = require('../../utils/util.js')
const app = getApp()
Page({
data: {
curLang: {},
langList: app.globalData.langList
},
onShow: function () {
this.setData({ curLang: app.globalData.curLang })
},
onTapItem: function(e) {
let langObj = e.currentTarget.dataset
wx.setStorageSync('language', langObj)
this.setData({'curLang': langObj})
app.globalData.curLang = langObj
wx.switchTab({ url: '/pages/index/index'})
}
})
`
app.js
切换的语言钟类可以去百度翻译里查看,小七翻译支持中,英,日,韩,法,西班牙,阿拉伯,泰,希腊,瑞典,保加利亚等等多国国家语言的互翻。
wx.setStorageSync
**wx.setStorageSync(string key, Object|string data) **
1.string key:本地缓存中指定的key
2.Object|string data : 需要存储的内容
wx.getStorageSync
Object|string wx.getStorageSync(string key)
wx.switchTab
wx.switchTab跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
onTapItem事件
在执行onTapItem事件时,可以得到参数e,并且e.currentTarget.dataset可以储存自定义的属性,以便于页面使用
这里需要一个函数来保存变量,便于翻译,和选择语言的时候引用。并且下次打开时数据都在,把这个函数写在app.js,代码如下。
//app.js
App({
onLaunch: function () {
// 展示本地存储能力
this.globalData.curLang = wx.getStorageSync('curLang') || this.globalData.langList[0]
},
globalData: {
curLang: {},
langList: [
{
'chs': '英文',
"lang": 'en',
"index": 0
},
{
'chs': '中文',
'lang': 'zh',
"index": 1
},
{
'chs': '日语',
'lang': 'jp',
"index": 2
},
{
'chs': '韩语',
'lang': 'kor',
"index": 3
},
{
'chs': '法语',
'lang': 'fra',
"index": 4
},
{
'chs': '西班牙语',
'lang': 'spa',
"index": 5
},
{
'chs': '阿拉伯语',
'lang': 'ara',
"index": 6
},
{
'chs': '粤语',
'lang': 'yue',
"index": 7
},
{
'chs': '泰语',
'lang': 'th',
"index": 8
},
{
'chs': '繁体中文',
'lang': 'cht',
"index": 9
},
{
'chs': '希腊语',
'lang': 'el',
"index": 10
},
{
'chs': '文言文',
'lang': 'wyw',
"index": 11
}, {
'chs': '瑞典语',
'lang': 'swe',
"index": 12
},
{
'chs': '保加利亚语',
'lang': 'bul',
"index": 13
},
]
},
})
history页面实现
history页面区域划分
history.wxml
当做一个数组去渲染,点击对应数组,跳转到index页面,进行当前语言翻译
<!--pages/history/history.wxml-->
<scroll-view scroll-y class="container">
<view class="history-list">
<view class="title">翻译历史</view>
<view class="item" wx:for="{{history}}" wx:key="index" bindtap='onTapItem' data-query="{{item.query}}" data-langId="{{item.langIndex}}" >
<view class="query">{{item.query}}</view>
<view class="result">{{item.result}}</view>
</view>
</view>
</scroll-view>
history.js
// pages/history/history.js
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
history: []
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
onShow: function () {
this.setData({ history: wx.getStorageSync('history')})
},
onTapItem: function(e) {
wx.reLaunch({
url: `/pages/index/index?query=${e.currentTarget.dataset.query}`
})
},
客服页面
客服功能页面展示
怎么给项目添加客服功能呢?很简单添加下面代码即可。
<!--pages/button/button.wxml-->
<view class="input-area">
<button class="iconfont icon-kefu" open-type="contact" bindcontact="handleContact">咨询客服</button>
</view>
此外还可以添加语音啊等各种功能,如有需求可以再添加。 这样翻译工具的最基本的功能就实现了
感悟
从零到有的这个过程,是非常美好的。
在这个项目的开发过程中我也遇到了各种问题,令我影响最深的是翻译功能的实现,虽然回头再看,也很简单,但是在自学的过程中,有很多不理解的问题,我最大的感受是,如果在自学的过程中遇到了一些不懂的知识,你可以先不理解,先去用,你的功能实现了后,你再回过头去理解,那样你才会理解它,自学是件困难的事情,在学习过程中我会遇到各种不懂得东西,然后自己去查资料,去学习它,有些知识,其实你会用它了,自然也就理解了。
这次小程序开发的学习中,从开发者工具的下载,小程序文档的阅读,小程序组件的学习于与运用,到各种api的使用,logo的设计,再到小程序的完成,都是我第一次接触,小七翻译发布后正式上线,把小程序码分享给朋友,他们通过客服给我反馈,整个体验使我非常开心,根据自己的需求开发出来了项目也学到的更多的东西,有了不一样的体验。