diff --git a/app/src/main/java/com/example/defenseapplication/MyApplication.kt b/app/src/main/java/com/example/defenseapplication/MyApplication.kt index d21b4b5..69f1235 100644 --- a/app/src/main/java/com/example/defenseapplication/MyApplication.kt +++ b/app/src/main/java/com/example/defenseapplication/MyApplication.kt @@ -1,10 +1,20 @@ package com.example.defenseapplication import android.app.Application -import com.blankj.utilcode.util.Utils; -class MyApplication : Application(){ +import android.content.Context +import com.blankj.utilcode.util.Utils +import com.example.defenseapplication.utils.LanguageUtil + +class MyApplication : Application() { + override fun onCreate() { super.onCreate() Utils.init(this) // 初始化 AndroidUtilCode } -} \ No newline at end of file + + override fun attachBaseContext(base: Context) { + // 在应用启动时应用语言设置 + val context = LanguageUtil.attachBaseContext(base) + super.attachBaseContext(context) + } +} diff --git a/app/src/main/java/com/example/defenseapplication/base/BaseActivity.kt b/app/src/main/java/com/example/defenseapplication/base/BaseActivity.kt new file mode 100644 index 0000000..aba4456 --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/base/BaseActivity.kt @@ -0,0 +1,38 @@ +package com.example.defenseapplication.base + +import android.content.Context +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.example.defenseapplication.utils.LanguageUtil + +/** + * 支持语言切换的 Activity 基类 + * 所有需要支持多语言的 Activity 都应该继承此类 + */ +abstract class BaseActivity : AppCompatActivity() { + + override fun attachBaseContext(newBase: Context) { + // 在 Activity 创建前应用语言设置 + val context = LanguageUtil.attachBaseContext(newBase) + super.attachBaseContext(context) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + // 确保语言设置被应用 + LanguageUtil.updateResources(this) + } + + /** + * 切换语言 + * 调用后会重新创建 Activity 以应用新语言 + */ + protected fun switchLanguage(language: String) { + val currentLang = LanguageUtil.getCurrentLanguage(this) + if (currentLang != language) { + LanguageUtil.switchLanguage(this, language) + // 重新创建 Activity 以应用新语言 + recreate() + } + } +} diff --git a/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt b/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt index 71383b3..15d3be2 100644 --- a/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt @@ -6,6 +6,7 @@ import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.GridLayoutManager +import com.example.defenseapplication.R import com.example.defenseapplication.adapter.AddDeviceAdapter import com.example.defenseapplication.adapter.Device import com.example.defenseapplication.databinding.AddDeviceActivityBinding @@ -32,8 +33,8 @@ class AddDeviceActivity : AppCompatActivity() { private fun setupDeviceList() { val devices = listOf( - Device("智能挂式防御机", "device1"), - Device("智能防御机", "device2") + Device(getString(R.string.smart_hanging_defense), "device1"), + Device(getString(R.string.smart_defense_device), "device2") ) if (devices.isEmpty()) { diff --git a/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt b/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt index f7b7287..ef5bc9d 100644 --- a/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt +++ b/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt @@ -1,6 +1,7 @@ package com.example.defenseapplication.home import android.content.Intent +import android.content.res.Resources import android.graphics.Color import android.graphics.Rect import android.graphics.drawable.GradientDrawable @@ -13,6 +14,7 @@ import android.view.ViewGroup import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.example.defenseapplication.R import com.example.defenseapplication.adapter.DeviceAdapter import com.example.defenseapplication.adapter.DeviceUi import com.example.defenseapplication.adapter.FamilyAdapter @@ -28,24 +30,32 @@ class HomeMenuFragment : Fragment() { private val deviceAdapter by lazy { DeviceAdapter(::onDeviceClicked) } private var isFamilyExpanded = false - private var currentFamily = "我的家庭" + private lateinit var currentFamily: String - private val familyList = listOf("我的家庭", "工作室", "父母家") - private val familyDeviceMap = mapOf( - "我的家庭" to listOf( - DeviceUi("智能挂式防御机", true), - DeviceUi("智能防御机", false), - DeviceUi("智能轨道防御机", false) - ), - "工作室" to listOf( - DeviceUi("走廊防御机", true), - DeviceUi("门禁防御机", true) - ), - "父母家" to listOf( - DeviceUi("客厅防御机", false), - DeviceUi("阳台防御机", true) + private val familyList: List by lazy { + listOf( + getString(R.string.my_family_home), + getString(R.string.workshop), + getString(R.string.parents_home) ) - ) + } + private val familyDeviceMap: Map> by lazy { + mapOf( + getString(R.string.my_family_home) to listOf( + DeviceUi(getString(R.string.smart_hanging_defense), true), + DeviceUi(getString(R.string.smart_defense_device), false), + DeviceUi(getString(R.string.smart_rail_defense), false) + ), + getString(R.string.workshop) to listOf( + DeviceUi(getString(R.string.corridor_defense), true), + DeviceUi(getString(R.string.door_defense), true) + ), + getString(R.string.parents_home) to listOf( + DeviceUi(getString(R.string.living_room_defense), false), + DeviceUi(getString(R.string.balcony_defense), true) + ) + ) + } override fun onCreateView( inflater: LayoutInflater, @@ -81,6 +91,7 @@ class HomeMenuFragment : Fragment() { } private fun initView() { + currentFamily = familyList.first() binding.rvFamilyList.layoutManager = LinearLayoutManager(requireContext()) binding.rvFamilyList.adapter = familyAdapter familyAdapter.submitList(familyList, currentFamily) @@ -133,7 +144,7 @@ class HomeMenuFragment : Fragment() { private fun onDeviceClicked(device: DeviceUi) { if (device.isOnline) return showDefenseDialog( - config = DefenseDialogs.deviceOfflineConfig() + config = DefenseDialogs.deviceOfflineConfig(requireContext()) ) } diff --git a/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt b/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt index 7ac7f96..054c4d0 100644 --- a/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt +++ b/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt @@ -10,6 +10,8 @@ import com.bumptech.glide.Glide import com.example.defenseapplication.R import com.example.defenseapplication.databinding.PersonalFragmentBinding import com.example.defenseapplication.personal.PersonalProfileActivity +import com.example.defenseapplication.utils.LanguageUtil +import com.example.defenseapplication.view.LanguageDialog import com.gyf.immersionbar.ImmersionBar class PersonalFragment : Fragment() { @@ -37,9 +39,36 @@ class PersonalFragment : Fragment() { val intent= Intent(requireContext(), PersonalProfileActivity::class.java) startActivity(intent) } + // 更新当前语言显示 + updateCurrentLanguageDisplay() + // 语言设置点击事件 + binding.itemLanguage.setOnClickListener { + showLanguageDialog() + } return binding.root } + + /** + * 更新当前语言显示 + */ + private fun updateCurrentLanguageDisplay() { + val currentLang = LanguageUtil.getCurrentLanguage(requireContext()) + binding.tvCurrentLanguage.text = LanguageUtil.getLanguageDisplayName(currentLang) + } + + /** + * 显示语言选择对话框 + */ + private fun showLanguageDialog() { + val dialog = LanguageDialog(requireContext()) { language -> + LanguageUtil.switchLanguage(requireContext(), language) + // 刷新当前页面以应用新语言 + requireActivity().recreate() + } + dialog.show() + } + override fun onDestroyView() { super.onDestroyView() _binding = null // 避免内存泄漏 diff --git a/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt b/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt index 73d2594..990b66e 100644 --- a/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt @@ -56,7 +56,7 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { if (isGranted) { startRecordingMode() } else { - Toast.makeText(this, "需要录音权限才能使用控制功能", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.recording_permission_needed, Toast.LENGTH_SHORT).show() isRecording = false } } @@ -108,29 +108,29 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { mp.isLooping = true mp.start() this@LiveVideoActivity.isPlaying = true - Toast.makeText(this@LiveVideoActivity, "视频准备完成", Toast.LENGTH_SHORT).show() + Toast.makeText(this@LiveVideoActivity, R.string.video_ready, Toast.LENGTH_SHORT).show() } setOnCompletionListener { this@LiveVideoActivity.isPlaying = false - Toast.makeText(this@LiveVideoActivity, "播放完成", Toast.LENGTH_SHORT).show() + Toast.makeText(this@LiveVideoActivity, R.string.playback_complete, Toast.LENGTH_SHORT).show() } setOnErrorListener { _, what, extra -> - Toast.makeText(this@LiveVideoActivity, "播放错误: $what, $extra", Toast.LENGTH_SHORT).show() + Toast.makeText(this@LiveVideoActivity, getString(R.string.video_error_format, what, extra), Toast.LENGTH_SHORT).show() releaseMediaPlayer() true } setOnBufferingUpdateListener { _, percent -> if (percent < 100) { - Toast.makeText(this@LiveVideoActivity, "缓冲中: $percent%", Toast.LENGTH_SHORT).show() + Toast.makeText(this@LiveVideoActivity, getString(R.string.buffering_format, percent), Toast.LENGTH_SHORT).show() } } } catch (e: IOException) { e.printStackTrace() - Toast.makeText(this@LiveVideoActivity, "无法加载视频", Toast.LENGTH_SHORT).show() + Toast.makeText(this@LiveVideoActivity, R.string.cannot_load_video, Toast.LENGTH_SHORT).show() } } } @@ -192,7 +192,7 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { } binding.llAlarmLog.setOnClickListener { - Toast.makeText(this, "查看告警日志", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.view_alarm_log, Toast.LENGTH_SHORT).show() } // 点击xq箭头跳转到AlarmLogActivity @@ -207,11 +207,11 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { if (mp.isPlaying) { mp.pause() isPlaying = false - Toast.makeText(this, "已暂停", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.paused, Toast.LENGTH_SHORT).show() } else { mp.start() isPlaying = true - Toast.makeText(this, "继续播放", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.resume_playback, Toast.LENGTH_SHORT).show() } } } @@ -250,7 +250,7 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { binding.ivFullscreen.setImageResource(com.example.defenseapplication.R.drawable.back) - Toast.makeText(this, "已进入全屏", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.entered_fullscreen, Toast.LENGTH_SHORT).show() } private fun exitFullscreen() { @@ -274,7 +274,7 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { binding.ivFullscreen.setImageResource(com.example.defenseapplication.R.drawable.full_screen) - Toast.makeText(this, "已退出全屏", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.exited_fullscreen, Toast.LENGTH_SHORT).show() } private fun toggleVoice() { @@ -283,11 +283,11 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { if (isVoiceEnabled) { mediaPlayer?.setVolume(1.0f, 1.0f) binding.ivVoice.setImageResource(com.example.defenseapplication.R.drawable.voice_on_open) - Toast.makeText(this, "声音已开启", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.sound_on, Toast.LENGTH_SHORT).show() } else { mediaPlayer?.setVolume(0.0f, 0.0f) binding.ivVoice.setImageResource(com.example.defenseapplication.R.drawable.voice) - Toast.makeText(this, "声音已关闭", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.sound_off, Toast.LENGTH_SHORT).show() } } @@ -296,10 +296,10 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { if (isLightOn) { binding.ivLight.setImageResource(com.example.defenseapplication.R.drawable.light_on_open) - Toast.makeText(this, "灯光已开启", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.light_on, Toast.LENGTH_SHORT).show() } else { binding.ivLight.setImageResource(com.example.defenseapplication.R.drawable.light_on) - Toast.makeText(this, "灯光已关闭", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.light_off, Toast.LENGTH_SHORT).show() } } @@ -344,7 +344,7 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { // 启动麦克风脉冲动画 //startMicPulseAnimation() - Toast.makeText(this, "开始控制模式", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.start_control_mode, Toast.LENGTH_SHORT).show() } private fun stopRecordingMode() { @@ -365,7 +365,7 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { // 停止麦克风脉冲动画 stopMicPulseAnimation() - Toast.makeText(this, "停止控制模式", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.stop_control_mode, Toast.LENGTH_SHORT).show() } // private fun startMicPulseAnimation() { @@ -408,7 +408,7 @@ class LiveVideoActivity : AppCompatActivity(), SurfaceHolder.Callback { start() } catch (e: IOException) { e.printStackTrace() - Toast.makeText(this@LiveVideoActivity, "录音启动失败", Toast.LENGTH_SHORT).show() + Toast.makeText(this@LiveVideoActivity, R.string.recording_start_failed, Toast.LENGTH_SHORT).show() } } } diff --git a/app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt b/app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt index 483e761..639096b 100644 --- a/app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/liveVideo/SettingsActivity.kt @@ -1,13 +1,16 @@ package com.example.defenseapplication.liveVideo import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity +import com.example.defenseapplication.R +import com.example.defenseapplication.base.BaseActivity import com.example.defenseapplication.databinding.SettingsActivityBinding +import com.example.defenseapplication.utils.LanguageUtil import com.example.defenseapplication.view.CustomDialogFragmentText +import com.example.defenseapplication.view.LanguageDialog import com.example.defenseapplication.view.RecognitionModeDialog import com.gyf.immersionbar.ImmersionBar -class SettingsActivity : AppCompatActivity() { +class SettingsActivity : BaseActivity() { private lateinit var binding: SettingsActivityBinding @@ -34,8 +37,7 @@ class SettingsActivity : AppCompatActivity() { binding.itemDeviceName.setOnClickListener { val dialog = CustomDialogFragmentText() - .setTitle("设备名称") - .setInputHint("请输入设备名称") + .setTitle(getString(R.string.device_name)) .setInputText(binding.tvDeviceName.text.toString()) dialog.setOnConfirmListener { name -> binding.tvDeviceName.text = name @@ -45,15 +47,18 @@ class SettingsActivity : AppCompatActivity() { binding.itemUnbindDevice.setOnClickListener { val dialog = CustomDialogFragmentText() - .setTitle("提示") - .setMessage("确定解除该设备的绑定?") - .setNegativeText("取消") - .setPositiveText("确定") + .setTitle(getString(R.string.tip)) + .setMessage(getString(R.string.logout_confirm)) + .setNegativeText(getString(R.string.cancel)) + .setPositiveText(getString(R.string.confirm)) .setShowInput(false) dialog.setOnConfirmListener { finish() } dialog.show(supportFragmentManager, "CustomDialogFragment") } + + } -} \ No newline at end of file + +} diff --git a/app/src/main/java/com/example/defenseapplication/login/FaceLoginActivity.kt b/app/src/main/java/com/example/defenseapplication/login/FaceLoginActivity.kt index df1c5c9..24c403a 100644 --- a/app/src/main/java/com/example/defenseapplication/login/FaceLoginActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/login/FaceLoginActivity.kt @@ -35,7 +35,7 @@ class FaceLoginActivity : AppCompatActivity() { binding.btnStartVerification.setOnClickListener { val intent= Intent(this, FaceVerificationActivity::class.java) startActivity(intent) - Toast.makeText(this, "跳转到人脸识别页面", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.redirect_face_recognition_page, Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/java/com/example/defenseapplication/login/LoginActivity.kt b/app/src/main/java/com/example/defenseapplication/login/LoginActivity.kt index 78d7cda..3d1df4a 100644 --- a/app/src/main/java/com/example/defenseapplication/login/LoginActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/login/LoginActivity.kt @@ -114,24 +114,24 @@ class LoginActivity : AppCompatActivity() { binding.loginBtn.setOnClickListener { val phone = binding.etPhone.text.toString() if (phone.isEmpty()) { - Toast.makeText(this, "请输入手机号", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.enter_phone_number, Toast.LENGTH_SHORT).show() return@setOnClickListener } when (currentLoginMode) { LoginMode.SMS -> { val code = binding.etSmsCode.text.toString() if (code.isEmpty()) { - Toast.makeText(this, "请输入验证码", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.enter_verification_code_pls, Toast.LENGTH_SHORT).show() } else { - Toast.makeText(this, "验证码登录成功\n手机号:$phone\n验证码:$code", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.sms_login_success, phone, code), Toast.LENGTH_SHORT).show() } } LoginMode.PASSWORD -> { val pwd = binding.etPassword.text.toString() if (pwd.isEmpty()) { - Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.password_hint, Toast.LENGTH_SHORT).show() } else { - Toast.makeText(this, "密码登录成功\n手机号:$phone\n密码:$pwd", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.password_login_success, phone, pwd), Toast.LENGTH_SHORT).show() } } } @@ -140,23 +140,23 @@ class LoginActivity : AppCompatActivity() { binding.sendCodeBtn.setOnClickListener { val phone = binding.etPhone.text.toString() if (phone.isEmpty()) { - Toast.makeText(this, "请先输入手机号", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.phone_hint, Toast.LENGTH_SHORT).show() return@setOnClickListener } - Toast.makeText(this, "验证码已发送至 $phone", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.code_sent_to, phone), Toast.LENGTH_SHORT).show() startCountDown() } binding.registerText.setOnClickListener { val intent= Intent(this, RegisterActivity::class.java) startActivity(intent) - Toast.makeText(this, "跳转到注册页面", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.redirect_register_page, Toast.LENGTH_SHORT).show() } binding.forgetText.setOnClickListener { val intent= Intent(this, ForgetPasswordActivity::class.java) startActivity(intent) - Toast.makeText(this, "找回密码", Toast.LENGTH_SHORT).show() + Toast.makeText(this, R.string.forgot_password_page, Toast.LENGTH_SHORT).show() } } @@ -164,10 +164,10 @@ class LoginActivity : AppCompatActivity() { binding.sendCodeBtn.isEnabled = false object : CountDownTimer(60000, 1000) { override fun onTick(millisUntilFinished: Long) { - binding.sendCodeBtn.text = "${millisUntilFinished / 1000}秒后重试" + binding.sendCodeBtn.text = getString(R.string.countdown_retry, millisUntilFinished / 1000) } override fun onFinish() { - binding.sendCodeBtn.text = "发送验证码" + binding.sendCodeBtn.text = getString(R.string.send_code) binding.sendCodeBtn.isEnabled = true } }.start() diff --git a/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt b/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt index 3768402..800fcde 100644 --- a/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt @@ -39,7 +39,7 @@ class PersonalProfileActivity : AppCompatActivity() { .circleCrop() .into(binding.ivAvatar) - binding.tvNickname.text = "这里是我的昵称" + binding.tvNickname.text = getString(R.string.nickname_default) binding.tvPhone.text = "13589898989" // 点击行可跳转到“修改昵称/修改手机号”等页面 diff --git a/app/src/main/java/com/example/defenseapplication/utils/LanguageUtil.kt b/app/src/main/java/com/example/defenseapplication/utils/LanguageUtil.kt new file mode 100644 index 0000000..ecc5778 --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/utils/LanguageUtil.kt @@ -0,0 +1,115 @@ +package com.example.defenseapplication.utils + +import android.content.Context +import android.content.SharedPreferences +import android.content.res.Configuration +import android.content.res.Resources +import android.os.Build +import android.os.LocaleList +import java.util.Locale + +object LanguageUtil { + + private const val PREF_NAME = "language_pref" + private const val KEY_LANGUAGE = "selected_language" + + const val LANGUAGE_CHINESE = "zh" + const val LANGUAGE_ENGLISH = "en" + + /** + * 切换语言 + * @param context 上下文 + * @param language 语言代码: "zh" 中文, "en" 英文 + */ + fun switchLanguage(context: Context, language: String) { + saveLanguage(context, language) + } + + /** + * 获取当前设置的语言 + */ + fun getCurrentLanguage(context: Context): String { + val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) + return prefs.getString(KEY_LANGUAGE, LANGUAGE_CHINESE) ?: LANGUAGE_CHINESE + } + + /** + * 保存语言设置 + */ + private fun saveLanguage(context: Context, language: String) { + val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) + prefs.edit().putString(KEY_LANGUAGE, language).apply() + } + + /** + * 判断当前是否是中文 + */ + fun isChinese(context: Context): Boolean { + return getCurrentLanguage(context) == LANGUAGE_CHINESE + } + + /** + * 获取本地化的 Context(用于在应用内切换语言) + * 在 attachBaseContext 中调用 + */ + fun attachBaseContext(context: Context): Context { + val language = getCurrentLanguage(context) + return createLocalizedContext(context, language) + } + + /** + * 创建本地化的 Context + */ + private fun createLocalizedContext(context: Context, language: String): Context { + val locale = Locale(language) + Locale.setDefault(locale) + + val resources = context.resources + val configuration = resources.configuration + + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + // Android 7.0 及以上 + val localeList = LocaleList(locale) + configuration.setLocales(localeList) + context.createConfigurationContext(configuration) + } else { + // Android 7.0 以下 + configuration.locale = locale + resources.updateConfiguration(configuration, resources.displayMetrics) + context + } + } + + /** + * 更新应用语言(用于在 Activity 中动态切换) + */ + fun updateResources(context: Context): Context { + val language = getCurrentLanguage(context) + val locale = Locale(language) + Locale.setDefault(locale) + + val resources = context.resources + val configuration = resources.configuration + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + val localeList = LocaleList(locale) + configuration.setLocales(localeList) + } else { + configuration.locale = locale + } + + resources.updateConfiguration(configuration, resources.displayMetrics) + return context + } + + /** + * 获取语言显示名称 + */ + fun getLanguageDisplayName(language: String): String { + return when (language) { + LANGUAGE_CHINESE -> "中文" + LANGUAGE_ENGLISH -> "English" + else -> "中文" + } + } +} diff --git a/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt b/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt index 0bcc17e..710a041 100644 --- a/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt +++ b/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt @@ -19,8 +19,8 @@ class CustomDialogFragmentText : DialogFragment() { private var message: String = "" private var inputHint: String = "" private var inputText: String = "" - private var negativeText: String = "取消" - private var positiveText: String = "确定" + private var negativeText: String = "" + private var positiveText: String = "" private var showInput: Boolean = true private var onConfirmListener: ((String) -> Unit)? = null @@ -87,6 +87,9 @@ class CustomDialogFragmentText : DialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // Set defaults if not explicitly configured + if (negativeText.isEmpty()) negativeText = getString(R.string.cancel) + if (positiveText.isEmpty()) positiveText = getString(R.string.confirm) binding.tvTitle.text = title binding.tvMessage.text = message binding.etInput.hint = inputHint diff --git a/app/src/main/java/com/example/defenseapplication/view/DialogFragment.kt b/app/src/main/java/com/example/defenseapplication/view/DialogFragment.kt index 67b6551..739b39a 100644 --- a/app/src/main/java/com/example/defenseapplication/view/DialogFragment.kt +++ b/app/src/main/java/com/example/defenseapplication/view/DialogFragment.kt @@ -183,41 +183,41 @@ object DefenseDialogs { .also { it.show(fragment.parentFragmentManager, tag) } } - fun intrusionAlertConfig(deviceName: String, timeText: String): CustomDialogFragment.Config { + fun intrusionAlertConfig(ctx: android.content.Context, deviceName: String, timeText: String): CustomDialogFragment.Config { return CustomDialogFragment.Config( - title = "入侵告警", - message = "${timeText}有人入侵\n【${deviceName}】", - positiveText = "去看一下", - negativeText = "取消" + title = ctx.getString(R.string.intrusion_alarm), + message = "${timeText}${ctx.getString(R.string.someone_invaded)}\n【${deviceName}】", + positiveText = ctx.getString(R.string.go_check), + negativeText = ctx.getString(R.string.cancel) ) } - fun warmPromptConfig(deviceName: String, runDays: Int): CustomDialogFragment.Config { + fun warmPromptConfig(ctx: android.content.Context, deviceName: String, runDays: Int): CustomDialogFragment.Config { return CustomDialogFragment.Config( - title = "温馨提示", - message = "【${deviceName}】设备已经运行\n${runDays}天请及时维护", - positiveText = "知道了", + title = ctx.getString(R.string.notice), + message = "【${deviceName}】${ctx.getString(R.string.device_running_days, runDays)}", + positiveText = ctx.getString(R.string.got_it), negativeText = null ) } - fun deviceOfflineConfig(): CustomDialogFragment.Config { + fun deviceOfflineConfig(ctx: android.content.Context): CustomDialogFragment.Config { return CustomDialogFragment.Config( - title = "设备离线", - message = "设备已离线,请检查设备的WIF及电\n源情况", - positiveText = "知道了", + title = ctx.getString(R.string.device_offline), + message = ctx.getString(R.string.device_offline_message), + positiveText = ctx.getString(R.string.got_it), negativeText = null ) } - fun strikeDistanceConfig(defaultDistance: String): CustomDialogFragment.Config { + fun strikeDistanceConfig(ctx: android.content.Context, defaultDistance: String): CustomDialogFragment.Config { return CustomDialogFragment.Config( - title = "打击距离", + title = ctx.getString(R.string.strike_distance), message = "", - positiveText = "确定", - negativeText = "取消", + positiveText = ctx.getString(R.string.confirm), + negativeText = ctx.getString(R.string.cancel), showInput = true, - inputHint = "请输入打击距离", + inputHint = ctx.getString(R.string.enter_strike_distance), inputText = defaultDistance, inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL ) diff --git a/app/src/main/java/com/example/defenseapplication/view/LanguageDialog.kt b/app/src/main/java/com/example/defenseapplication/view/LanguageDialog.kt new file mode 100644 index 0000000..b652159 --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/view/LanguageDialog.kt @@ -0,0 +1,63 @@ +package com.example.defenseapplication.view + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.Window +import android.widget.LinearLayout +import android.widget.TextView +import com.example.defenseapplication.R +import com.example.defenseapplication.utils.LanguageUtil + +/** + * 语言选择对话框 + */ +class LanguageDialog( + context: Context, + private val onLanguageSelected: (String) -> Unit +) : Dialog(context) { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + requestWindowFeature(Window.FEATURE_NO_TITLE) + setContentView(R.layout.dialog_language) + + // 设置对话框宽度为屏幕宽度的80% + window?.setLayout( + (context.resources.displayMetrics.widthPixels * 0.8).toInt(), + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + initViews() + } + + private fun initViews() { + val tvChinese = findViewById(R.id.tvChinese) + val tvEnglish = findViewById(R.id.tvEnglish) + val tvCancel = findViewById(R.id.tvCancel) + + val currentLang = LanguageUtil.getCurrentLanguage(context) + + // 根据当前语言高亮显示 + if (currentLang == LanguageUtil.LANGUAGE_CHINESE) { + tvChinese.setTextColor(context.getColor(R.color.green)) + } else { + tvEnglish.setTextColor(context.getColor(R.color.green)) + } + + tvChinese.setOnClickListener { + onLanguageSelected(LanguageUtil.LANGUAGE_CHINESE) + dismiss() + } + + tvEnglish.setOnClickListener { + onLanguageSelected(LanguageUtil.LANGUAGE_ENGLISH) + dismiss() + } + + tvCancel.setOnClickListener { + dismiss() + } + } +} diff --git a/app/src/main/java/com/example/defenseapplication/view/RecognitionModeDialog.kt b/app/src/main/java/com/example/defenseapplication/view/RecognitionModeDialog.kt index 932095d..3cfc170 100644 --- a/app/src/main/java/com/example/defenseapplication/view/RecognitionModeDialog.kt +++ b/app/src/main/java/com/example/defenseapplication/view/RecognitionModeDialog.kt @@ -39,12 +39,12 @@ class RecognitionModeDialog(context: Context) : Dialog(context) { } binding.itemBluetooth.setOnClickListener { - selectedMode = "蓝牙识别" + selectedMode = context.getString(R.string.bluetooth_recognition) updateSelectedBackground(binding.itemBluetooth) } binding.itemBluetoothFace.setOnClickListener { - selectedMode = "蓝牙+人脸识别" + selectedMode = context.getString(R.string.bluetooth_face_recognition) updateSelectedBackground(binding.itemBluetoothFace) } diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 4b32863..8651614 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -24,7 +24,7 @@ android:id="@+id/logoText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="智能防御机" + android:text="@string/login_title" android:textSize="26dp" android:textStyle="bold" android:textColor="@color/black" @@ -53,7 +53,7 @@ android:gravity="center" android:paddingTop="16dp" android:paddingBottom="16dp" - android:text="验证码登录" + android:text="@string/sms_login" android:textColor="@color/black" android:textSize="18sp" app:layout_constraintStart_toStartOf="parent" @@ -64,7 +64,7 @@ android:id="@+id/tvPwdLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="密码登录" + android:text="@string/password_login" android:textSize="18sp" android:gravity="center" android:paddingTop="16dp" @@ -98,7 +98,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:hint="请输入手机号" + android:hint="@string/phone_hint" android:textColorHint="@color/gray" android:textColor="@android:color/black" android:background="@null" @@ -142,7 +142,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:hint="请输入验证码" + android:hint="@string/sms_code_hint" android:textColorHint="@color/gray" android:textColor="@android:color/black" android:background="@null" @@ -158,7 +158,7 @@ android:id="@+id/sendCodeBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="发送验证码" + android:text="@string/send_sms_code" android:textSize="16sp" android:textColor="@color/white" android:background="@drawable/rounded_blue_bg" @@ -201,7 +201,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:hint="请输入密码" + android:hint="@string/password_hint" android:textColorHint="@color/gray" android:textColor="@android:color/black" android:background="@null" @@ -221,7 +221,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="40dp" - android:text="登录" + android:text="@string/login" android:textSize="18sp" android:background="@drawable/rounded_blue_bg" android:textColor="@color/white" @@ -234,7 +234,7 @@ android:id="@+id/registerText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="立即注册" + android:text="@string/register" android:textSize="14sp" android:textColor="@color/green" android:padding="8dp" @@ -247,7 +247,7 @@ android:id="@+id/forgetText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="忘记密码" + android:text="@string/forgot_password" android:textSize="14sp" android:textColor="@color/green" android:padding="8dp" diff --git a/app/src/main/res/layout/add_device_activity.xml b/app/src/main/res/layout/add_device_activity.xml index 0f75742..a7231ad 100644 --- a/app/src/main/res/layout/add_device_activity.xml +++ b/app/src/main/res/layout/add_device_activity.xml @@ -30,7 +30,7 @@ android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="添加设备" + android:text="@string/add_device_title" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" @@ -58,7 +58,7 @@ android:id="@+id/tvScanTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="扫描附近设备" + android:text="@string/scan_nearby" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" /> @@ -68,7 +68,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="持续自动搜索中..." + android:text="@string/scanning" android:textColor="@color/gray" android:textSize="14dp" /> @@ -96,7 +96,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="请将手机尽量靠近要添加的设备" + android:text="@string/device_nearby_hint" android:textColor="@color/gray" android:textSize="14dp" /> @@ -119,7 +119,7 @@ android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:background="@drawable/rounded_blue_bg" - android:text="扫描添加" + android:text="@string/scan_add" android:textColor="@color/white" android:textSize="16dp" android:textStyle="bold" diff --git a/app/src/main/res/layout/add_family_activity.xml b/app/src/main/res/layout/add_family_activity.xml index 9a0ae7d..48b27b3 100644 --- a/app/src/main/res/layout/add_family_activity.xml +++ b/app/src/main/res/layout/add_family_activity.xml @@ -32,7 +32,7 @@ android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="选择Wi-Fi" + android:text="@string/select_wifi" android:textColor="@color/black" android:textSize="18sp" android:textStyle="bold" @@ -68,7 +68,7 @@ android:layout_marginStart="12dp" android:layout_weight="1" android:background="@null" - android:hint="请输入WiFi名称" + android:hint="@string/enter_wifi_name" android:textColor="@color/black" android:textSize="16sp" /> @@ -78,7 +78,7 @@ android:layout_height="32dp" android:layout_marginStart="12dp" android:background="@drawable/rounded_blue_bg" - android:text="选择Wi-Fi" + android:text="@string/select_wifi" android:textColor="@color/white" android:textSize="14sp" /> @@ -103,7 +103,7 @@ android:layout_height="wrap_content" android:layout_marginStart="12dp" android:background="@null" - android:hint="请输入WiFi密码" + android:hint="@string/enter_wifi_password" android:inputType="textPassword" android:textColor="@color/black" android:textSize="16sp" /> @@ -132,7 +132,7 @@ android:layout_width="match_parent" android:layout_height="40dp" android:background="@drawable/rounded_blue_bg" - android:text="下一步" + android:text="@string/next_step" android:textColor="@color/white" android:textSize="16dp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/alarm_log_activity.xml b/app/src/main/res/layout/alarm_log_activity.xml index 2ace791..508de24 100644 --- a/app/src/main/res/layout/alarm_log_activity.xml +++ b/app/src/main/res/layout/alarm_log_activity.xml @@ -27,7 +27,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" - android:text="告警日志" + android:text="@string/alarm_log_title" android:textSize="16sp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/dialog_language.xml b/app/src/main/res/layout/dialog_language.xml new file mode 100644 index 0000000..5c4239c --- /dev/null +++ b/app/src/main/res/layout/dialog_language.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_recognition_mode.xml b/app/src/main/res/layout/dialog_recognition_mode.xml index d35f265..9940726 100644 --- a/app/src/main/res/layout/dialog_recognition_mode.xml +++ b/app/src/main/res/layout/dialog_recognition_mode.xml @@ -16,7 +16,7 @@ android:id="@+id/tv_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="取消" + android:text="@string/cancel" android:textColor="@color/black" android:textSize="16sp" /> @@ -29,7 +29,7 @@ android:id="@+id/tv_confirm" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="确认" + android:text="@string/confirm" android:textColor="@color/green" android:textSize="16sp" /> @@ -59,7 +59,7 @@ @@ -79,7 +79,7 @@ diff --git a/app/src/main/res/layout/dialog_wifi_list.xml b/app/src/main/res/layout/dialog_wifi_list.xml index e95b989..4586cc0 100644 --- a/app/src/main/res/layout/dialog_wifi_list.xml +++ b/app/src/main/res/layout/dialog_wifi_list.xml @@ -10,7 +10,7 @@ android:layout_width="match_parent" android:layout_height="56dp" android:gravity="center" - android:text="选择Wi-Fi" + android:text="@string/select_wifi" android:textColor="@color/black" android:textSize="18sp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/face_login_activity.xml b/app/src/main/res/layout/face_login_activity.xml index 113d093..c3b53c1 100644 --- a/app/src/main/res/layout/face_login_activity.xml +++ b/app/src/main/res/layout/face_login_activity.xml @@ -31,7 +31,7 @@ android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="人脸识别" + android:text="@string/face_recognition" android:textColor="@color/black" android:textSize="16sp" android:textStyle="bold" @@ -47,7 +47,7 @@ android:id="@+id/tvRegisterSubtitle" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="人脸验证" + android:text="@string/face_verification" android:textColor="@color/black" android:textSize="20dp" android:textStyle="bold" @@ -78,7 +78,7 @@ android:id="@+id/tvSubTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="仅用于创建防御机制和防窃取,保障您的安全" + android:text="@string/face_security_notice" android:textColor="@color/green" android:textSize="12sp" android:textStyle="bold" @@ -106,7 +106,7 @@ android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="11dp" - android:text="请根据指示完成人脸验证" + android:text="@string/follow_instructions" android:textColor="@color/icon_face" android:textSize="12dp" android:textStyle="bold" @@ -152,7 +152,7 @@ android:layout_marginLeft="5dp" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="标准拍摄" + android:text="@string/standard_capture" android:textColor="@color/icon_face" android:textSize="12dp" android:textStyle="bold"/> @@ -188,7 +188,7 @@ android:layout_marginLeft="5dp" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="标准拍摄" + android:text="@string/standard_capture" android:textColor="@color/icon_face" android:textSize="12dp" android:textStyle="bold"/> @@ -224,7 +224,7 @@ android:layout_marginLeft="5dp" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="拍摄不全" + android:text="@string/incomplete_capture" android:textColor="@color/icon_face" android:textSize="12dp" android:textStyle="bold"/> @@ -260,7 +260,7 @@ android:layout_marginLeft="5dp" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="光线不足" + android:text="@string/insufficient_light" android:textColor="@color/icon_face" android:textSize="12dp" android:textStyle="bold"/> @@ -279,7 +279,7 @@ android:layout_marginBottom="16dp" android:layout_marginStart="25dp" android:layout_marginEnd="25dp" - android:text="开始验证" + android:text="@string/start_verification" android:textColor="@color/white" android:textSize="14dp" android:textStyle="bold" diff --git a/app/src/main/res/layout/face_verification_activity.xml b/app/src/main/res/layout/face_verification_activity.xml index bed96b9..151cbbb 100644 --- a/app/src/main/res/layout/face_verification_activity.xml +++ b/app/src/main/res/layout/face_verification_activity.xml @@ -50,7 +50,7 @@ android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="人脸采集" + android:text="@string/face_collection" android:textColor="@android:color/white" android:textSize="22sp" android:textStyle="bold" @@ -84,7 +84,7 @@ android:id="@+id/tvFaceHint" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="请将人脸放入圆形区域内" + android:text="@string/face_in_circle" android:textColor="@android:color/white" android:textSize="20sp" android:textStyle="bold" @@ -109,7 +109,7 @@ android:id="@+id/btnCaptureFace" android:layout_width="match_parent" android:layout_height="50dp" - android:text="采集人脸" + android:text="@string/collect_face" android:textAllCaps="false" android:textSize="17sp" android:textStyle="bold" diff --git a/app/src/main/res/layout/forget_password_activity.xml b/app/src/main/res/layout/forget_password_activity.xml index dd30e22..09a7012 100644 --- a/app/src/main/res/layout/forget_password_activity.xml +++ b/app/src/main/res/layout/forget_password_activity.xml @@ -31,7 +31,7 @@ android:id="@+id/tvRegisterTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="找回密码" + android:text="@string/retrieve_password" android:textColor="@color/black" android:textSize="32sp" android:textStyle="bold" @@ -47,7 +47,7 @@ android:id="@+id/tvRegisterSubtitle" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="找回密码" + android:text="@string/retrieve_password" android:textColor="@color/black" android:textSize="20dp" android:textStyle="bold" @@ -84,7 +84,7 @@ android:layout_height="wrap_content" android:layout_marginStart="12dp" android:background="@null" - android:hint="请输入手机号" + android:hint="@string/enter_phone_number" android:inputType="phone" android:maxLength="11" android:paddingVertical="16dp" @@ -128,7 +128,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:hint="请输入验证码" + android:hint="@string/enter_verification_code" android:textColorHint="@color/gray" android:textColor="@android:color/black" android:background="@null" @@ -144,7 +144,7 @@ android:id="@+id/sendCodeBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="发送验证码" + android:text="@string/send_code" android:textSize="16sp" android:textColor="@color/white" android:background="@drawable/rounded_blue_bg" @@ -185,7 +185,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:hint="请输入新密码" + android:hint="@string/enter_new_password" android:textColorHint="@color/gray" android:textColor="@android:color/black" android:background="@null" @@ -226,7 +226,7 @@ android:layout_height="wrap_content" android:layout_marginStart="12dp" android:background="@null" - android:hint="请再次输入新密码" + android:hint="@string/enter_password_again" android:inputType="text" android:maxLength="10" android:paddingVertical="16dp" @@ -246,7 +246,7 @@ android:layout_width="0dp" android:layout_height="56dp" android:layout_marginTop="32dp" - android:text="确定" + android:text="@string/determine" android:textAllCaps="false" android:textSize="16sp" app:cornerRadius="12dp" diff --git a/app/src/main/res/layout/home_activity.xml b/app/src/main/res/layout/home_activity.xml index 6be7e0b..c5d5295 100644 --- a/app/src/main/res/layout/home_activity.xml +++ b/app/src/main/res/layout/home_activity.xml @@ -45,7 +45,7 @@ android:id="@+id/tv_home" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="首页" + android:text="@string/home" android:textSize="12sp" android:textColor="@color/black"/> @@ -70,7 +70,7 @@ android:id="@+id/tv_profile" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="个人" + android:text="@string/profile" android:textSize="12sp" android:textColor="@color/gray"/> diff --git a/app/src/main/res/layout/home_menu_fragment.xml b/app/src/main/res/layout/home_menu_fragment.xml index 52ec5d2..3e858a1 100644 --- a/app/src/main/res/layout/home_menu_fragment.xml +++ b/app/src/main/res/layout/home_menu_fragment.xml @@ -38,7 +38,7 @@ android:id="@+id/tvCurrentFamily" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="我的家庭" + android:text="@string/my_family_home" android:textColor="@color/black" android:textSize="20dp" android:textStyle="bold" /> @@ -111,7 +111,7 @@ android:layout_height="wrap_content" android:layout_marginTop="14dp" android:layout_marginEnd="16dp" - android:text="设备" + android:text="@string/device" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/live_video_activity.xml b/app/src/main/res/layout/live_video_activity.xml index 63960b2..0ef3109 100644 --- a/app/src/main/res/layout/live_video_activity.xml +++ b/app/src/main/res/layout/live_video_activity.xml @@ -29,7 +29,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" - android:text="智能防御机A1" + android:text="@string/smart_device_a1" android:textSize="16sp" android:textStyle="bold" /> @@ -131,7 +131,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="语音" + android:text="@string/voice" android:textSize="14sp" android:textColor="@color/ic_normal"/> @@ -155,7 +155,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="灯光" + android:text="@string/light" android:textSize="14sp" android:textColor="@color/ic_normal"/> @@ -179,7 +179,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="控制" + android:text="@string/control" android:textSize="14sp" android:textColor="@color/ic_normal"/> @@ -229,7 +229,7 @@ @@ -286,7 +286,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="入侵告警" + android:text="@string/intrusion_detected" android:textColor="@color/black" android:textSize="14sp" android:textStyle="bold" /> @@ -331,7 +331,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="入侵告警" + android:text="@string/intrusion_detected" android:textColor="@color/black" android:textSize="14sp" android:textStyle="bold" /> @@ -379,7 +379,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="入侵告警" + android:text="@string/intrusion_detected" android:textColor="@color/black" android:textSize="14sp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/message_activity.xml b/app/src/main/res/layout/message_activity.xml index 2fa4e15..d4e1419 100644 --- a/app/src/main/res/layout/message_activity.xml +++ b/app/src/main/res/layout/message_activity.xml @@ -27,7 +27,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="消息列表" + android:text="@string/message_title" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold"/> diff --git a/app/src/main/res/layout/personal_fragment.xml b/app/src/main/res/layout/personal_fragment.xml index ff339db..3eadf9f 100644 --- a/app/src/main/res/layout/personal_fragment.xml +++ b/app/src/main/res/layout/personal_fragment.xml @@ -42,7 +42,7 @@ android:id="@+id/tvNickname" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="这里是昵称" + android:text="@string/enter_nickname" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" /> @@ -55,7 +55,7 @@ android:background="@drawable/rounded_blue_bg" android:gravity="center" android:paddingHorizontal="8dp" - android:text="管理员" + android:text="@string/admin" android:textColor="@color/white" android:textSize="11sp" android:textStyle="bold" /> @@ -92,7 +92,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" - android:text="切换家庭" + android:text="@string/switch_family" android:textColor="@color/black" android:textSize="16dp" /> @@ -102,7 +102,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:gravity="end" - android:text="我的家庭" + android:text="@string/my_family" android:textColor="@color/green" android:textSize="14dp" /> @@ -134,7 +134,7 @@ android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_weight="1" - android:text="用户管理" + android:text="@string/user_management" android:textColor="@color/black" android:textSize="16dp" /> @@ -165,7 +165,7 @@ android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_weight="1" - android:text="密码管理" + android:text="@string/password_management" android:textColor="@color/black" android:textSize="16dp" /> @@ -196,7 +196,7 @@ android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_weight="1" - android:text="人脸管理" + android:text="@string/face_management" android:textColor="@color/black" android:textSize="16dp" /> @@ -205,6 +205,44 @@ android:layout_height="16dp" android:src="@drawable/right_back" /> + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/personal_profile_activity.xml b/app/src/main/res/layout/personal_profile_activity.xml index cd1b63a..f879165 100644 --- a/app/src/main/res/layout/personal_profile_activity.xml +++ b/app/src/main/res/layout/personal_profile_activity.xml @@ -28,7 +28,7 @@ android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="个人资料" + android:text="@string/personal_info" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" @@ -84,7 +84,7 @@ @@ -127,7 +127,7 @@ diff --git a/app/src/main/res/layout/register_activity.xml b/app/src/main/res/layout/register_activity.xml index 775dc2e..9ea8967 100644 --- a/app/src/main/res/layout/register_activity.xml +++ b/app/src/main/res/layout/register_activity.xml @@ -31,7 +31,7 @@ android:id="@+id/tvRegisterTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="注册" + android:text="@string/register_title" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" @@ -48,7 +48,7 @@ android:id="@+id/tvRegisterSubtitle" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="注册用户" + android:text="@string/register_subtitle" android:textColor="@color/black" android:textSize="24dp" android:textStyle="bold" @@ -85,7 +85,7 @@ android:layout_height="wrap_content" android:layout_marginStart="12dp" android:background="@null" - android:hint="请输入手机号" + android:hint="@string/phone_hint" android:inputType="phone" android:maxLength="11" android:paddingVertical="16dp" @@ -127,7 +127,7 @@ android:layout_height="wrap_content" android:layout_marginStart="12dp" android:background="@null" - android:hint="请输入身份证号" + android:hint="@string/enter_id_number" android:inputType="text" android:maxLength="18" android:paddingVertical="16dp" @@ -170,7 +170,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:hint="请输入密码" + android:hint="@string/set_password" android:textColorHint="@color/gray" android:textColor="@android:color/black" android:background="@null" @@ -212,7 +212,7 @@ android:layout_height="wrap_content" android:layout_marginStart="12dp" android:background="@null" - android:hint="请输入邀请码(非必填)" + android:hint="@string/invite_code_optional" android:inputType="text" android:maxLength="10" android:paddingVertical="16dp" @@ -232,7 +232,7 @@ android:layout_width="0dp" android:layout_height="56dp" android:layout_marginTop="32dp" - android:text="下一步" + android:text="@string/next_step" android:textAllCaps="false" android:textSize="16sp" app:cornerRadius="12dp" diff --git a/app/src/main/res/layout/register_success_activity.xml b/app/src/main/res/layout/register_success_activity.xml index cf4ec51..fb9b74d 100644 --- a/app/src/main/res/layout/register_success_activity.xml +++ b/app/src/main/res/layout/register_success_activity.xml @@ -31,7 +31,7 @@ tools:context=".login.RegisterSuccessActivity"> android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="注册" + android:text="@string/register" android:textColor="@color/black" android:textSize="16sp" android:textStyle="bold" @@ -47,7 +47,7 @@ tools:context=".login.RegisterSuccessActivity"> android:id="@+id/tvRegisterSubtitle" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="注册用户" + android:text="@string/register_user" android:textColor="@color/black" android:textSize="20dp" android:textStyle="bold" @@ -76,7 +76,7 @@ tools:context=".login.RegisterSuccessActivity"> android:layout_marginBottom="16dp" android:layout_marginStart="25dp" android:layout_marginEnd="25dp" - android:text="进入平台(3S)" + android:text="@string/enter_platform" android:textColor="@color/white" android:textSize="14dp" android:textStyle="bold" diff --git a/app/src/main/res/layout/scan_activity.xml b/app/src/main/res/layout/scan_activity.xml index 6317961..5dfa6f2 100644 --- a/app/src/main/res/layout/scan_activity.xml +++ b/app/src/main/res/layout/scan_activity.xml @@ -109,7 +109,7 @@ android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="550dp" - android:text="请扫描设备或说明书上的二维码" + android:text="@string/scan_device_qr" android:textColor="@color/white" android:textSize="14sp" /> @@ -140,7 +140,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="相册" + android:text="@string/album" android:textColor="@color/white" android:textSize="12sp" /> @@ -164,7 +164,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="手电筒" + android:text="@string/flashlight" android:textColor="@color/white" android:textSize="12dp" /> diff --git a/app/src/main/res/layout/set_name_activity.xml b/app/src/main/res/layout/set_name_activity.xml index 95f5a43..b330634 100644 --- a/app/src/main/res/layout/set_name_activity.xml +++ b/app/src/main/res/layout/set_name_activity.xml @@ -28,7 +28,7 @@ android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="设置名字" + android:text="@string/set_name" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" @@ -49,7 +49,7 @@ android:id="@+id/tvLabel" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="设置名字" + android:text="@string/set_name" android:textColor="@color/black" android:textSize="16dp" /> @@ -59,9 +59,9 @@ android:layout_height="48dp" android:layout_marginTop="12dp" android:background="@drawable/textinput_white_bg" - android:hint="请输入设备名称" + android:hint="@string/enter_device_name" android:paddingHorizontal="16dp" - android:text="智能防御机A1" + android:text="@string/smart_device_a1" android:textColor="@color/black" android:textSize="14dp" /> @@ -77,7 +77,7 @@ android:layout_width="match_parent" android:layout_height="48dp" android:background="@drawable/rounded_blue_bg" - android:text="完成" + android:text="@string/complete" android:textColor="@color/white" android:textSize="16dp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml index e5ed615..df51b1b 100644 --- a/app/src/main/res/layout/settings_activity.xml +++ b/app/src/main/res/layout/settings_activity.xml @@ -25,7 +25,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" - android:text="设置" + android:text="@string/settings_title" android:textColor="@color/black" android:textSize="16dp" android:textStyle="bold" /> @@ -45,7 +45,7 @@ android:layout_height="wrap_content" android:paddingHorizontal="16dp" android:paddingVertical="12dp" - android:text="功能设置" + android:text="@string/function_settings" android:textColor="@color/gray" android:textSize="14dp" /> @@ -62,7 +62,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="语音设置" + android:text="@string/voice_settings" android:textColor="@color/black" android:textSize="16dp" /> @@ -91,7 +91,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="水枪设置" + android:text="@string/water_gun_settings" android:textColor="@color/black" android:textSize="16dp" /> @@ -120,7 +120,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="识别模式" + android:text="@string/recognition_mode" android:textColor="@color/black" android:textSize="16dp" /> @@ -134,7 +134,7 @@ android:id="@+id/tvRecognitionMode" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="蓝牙+人脸" + android:text="@string/mode_standard" android:textColor="@color/gray" android:textSize="14sp" /> @@ -165,7 +165,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="自动模式" + android:text="@string/detection_settings" android:textColor="@color/black" android:textSize="16dp" /> @@ -178,7 +178,7 @@ @@ -200,7 +200,7 @@ android:layout_height="wrap_content" android:paddingHorizontal="16dp" android:paddingVertical="12dp" - android:text="基本设置" + android:text="@string/settings" android:textColor="@color/gray" android:textSize="14dp" /> @@ -217,7 +217,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="设备名称" + android:text="@string/device_name" android:textColor="@color/black" android:textSize="16dp" /> @@ -231,7 +231,7 @@ android:id="@+id/tvDeviceName" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="智能防御机A1" + android:text="@string/device_name" android:textColor="@color/gray" android:textSize="14sp" /> @@ -262,7 +262,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="设备信息" + android:text="@string/about" android:textColor="@color/black" android:textSize="16dp" /> @@ -291,7 +291,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="关联用户" + android:text="@string/user_management" android:textColor="@color/black" android:textSize="16dp" /> @@ -304,7 +304,7 @@ @@ -335,7 +335,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="WiFi管理" + android:text="@string/wifi" android:textColor="@color/black" android:textSize="16dp" /> @@ -348,7 +348,7 @@ @@ -379,7 +379,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="解绑设备" + android:text="@string/unbind_device" android:textColor="@color/black" android:textSize="16dp" /> @@ -389,4 +389,12 @@ android:src="@drawable/right_back" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml new file mode 100644 index 0000000..f48e953 --- /dev/null +++ b/app/src/main/res/values-zh/strings.xml @@ -0,0 +1,335 @@ + + + + 防御器 + + + 确定 + 取消 + 保存 + 删除 + 编辑 + 返回 + 加载中... + 网络错误,请重试 + 发送 + 提交 + + + 智能防御机 + 验证码登录 + 密码登录 + 请输入手机号 + 请输入验证码 + 请输入密码 + 发送验证码 + 登录 + 忘记密码? + 注册 + + + 注册 + 注册用户 + 设置密码 + 确认密码 + 密码长度6-20位 + 我已阅读并同意 + 用户协议 + + 隐私政策 + 注册成功 + 您的账号已成功创建 + 去登录 + + + 忘记密码 + 重置密码 + 新密码 + 密码重置成功 + + + 人脸登录 + 人脸验证 + 请将人脸对准框内 + 识别成功 + 识别失败 + 重试 + + + 首页 + 个人 + + + 我的设备 + 添加设备 + 扫一扫 + 语音控制 + 灯光控制 + 水枪 + 监控 + 告警记录 + 消息 + 设置 + + + 设备名称 + 状态 + 在线 + 离线 + 设备ID + 绑定设备 + 解绑设备 + 暂无设备 + + + 添加设备 + 扫描附近设备 + 持续自动搜索中... + 请将手机尽量靠近要添加的设备 + 重新扫描 + 手动添加 + 请输入设备ID + 绑定成功 + + + 家庭管理 + 切换家庭 + 当前家庭 + 我的家庭 + 添加家庭 + 家庭名称 + 请输入家庭名称 + 创建家庭 + 加入家庭 + 家庭码 + 请输入家庭码 + + + 用户管理 + 用户列表 + 添加用户 + 管理员 + 成员 + 昵称 + 手机号 + 请输入昵称 + + + 密码管理 + 修改密码 + 当前密码 + 原密码 + 验证码 + + + 人脸管理 + 添加人脸 + 人脸列表 + 确定要删除这张人脸吗? + 标准采集 + 严格采集 + + + 实时监控 + 全屏 + 截图 + 录像 + 对讲 + 静音 + 取消静音 + 视频加载中... + 视频加载失败 + + + 告警记录 + 告警详情 + 告警时间 + 告警类型 + 告警位置 + 暂无告警记录 + 入侵检测 + 异常声音 + 移动侦测 + + + 消息 + 系统 + 告警 + 设备 + 暂无消息 + 标记已读 + 清空全部 + 消息详情 + + + 设置 + 功能设置 + 语音设置 + 水枪设置 + 侦测设置 + 通知设置 + 语言 + 中文 + English + 关于 + 版本 + 退出登录 + 确定要退出登录吗? + + + 个人信息 + 头像 + 性别 + + + 生日 + 地址 + 请输入地址 + + + 扫一扫 + 将二维码/条码放入框内,即可自动扫描 + 相册 + 手电筒 + 扫描失败,请重试 + + + WiFi列表 + WiFi密码 + 请输入WiFi密码 + 连接 + 连接中... + 连接失败 + 连接成功 + + + 提示 + 请稍候... + 操作成功 + 操作失败 + 网络不可用 + 请检查网络连接 + + + 识别模式 + 标准模式 + 严格模式 + 自定义模式 + + + 今天 + 昨天 + 本周 + 本月 + + + Hello blank fragment + + + 请扫描设备或说明书上的二维码 + 工作室 + 父母家 + 智能挂式防御机 + 智能防御机 + 智能轨道防御机 + 走廊防御机 + 门禁防御机 + 客厅防御机 + 阳台防御机 + 我的家庭 + 设备 + 智能防御机A1 + 语音 + 灯光 + 控制 + %d秒 + 注册用户 + 进入平台 + 这里是昵称 + 绑定手机 + 人脸识别 + 仅用于创建防御机制和防窃取,保障您的安全 + 请根据指示完成人脸验证 + 拍摄不全 + 光线不足 + 开始验证 + 选择Wi-Fi + 请输入WiFi名称 + 下一步 + 设置名字 + 请输入设备名称 + 完成 + 蓝牙识别 + 蓝牙+人脸识别 + 消息列表 + 人脸采集 + 请将人脸放入圆形区域内 + 采集人脸 + 找回密码 + 请输入手机号 + 请输入验证码 + 发送验证码 + 请输入新密码 + 请再次输入新密码 + 确定 + 身份证号 + 请输入身份证号 + 邀请码(非必填) + 请输入邀请码 + 扫描添加 + WiFi + 需要录音权限才能使用控制功能 + 视频准备完成 + 播放完成 + 无法加载视频 + 查看告警日志 + 已暂停 + 继续播放 + 已进入全屏 + 已退出全屏 + 声音已开启 + 声音已关闭 + 灯光已开启 + 灯光已关闭 + 开始控制模式 + 停止控制模式 + 录音启动失败 + 播放错误: %1$d, %2$d + 缓冲中: %d%% + 相机未准备好 + 无法打开相机 + 需要相机权限 + 已选择图片 + 请稍后再试 + 手机号格式不正确 + 请输入验证码 + 请先获取验证码 + 验证码错误 + 密码不能为空 + 密码需同时包含字母和数字 + 两次输入的密码不一致 + 跳转到人脸页面 + 跳转到注册页面 + 找回密码 + 跳转到人脸识别页面 + 需要相机权限才能进行人脸验证 + 入侵告警 + 设备故障 + 到期提醒 + 有人入侵 + 去看一下 + 温馨提示 + 知道了 + 打击距离 + 请输入打击距离 + 人脸检测失败 + 这里是我的昵称 + 设备已经运行\n%d天请及时维护 + 设备已离线,请检查设备的WIFI及电源情况 + %d秒后重试 + 验证码登录成功\n手机号:%1$s\n验证码:%2$s + 密码登录成功\n手机号:%1$s\n密码:%2$s + 验证码已发送至 %s + 登录成功 + 登录成功 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3e3c969..ca2fd4f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,335 @@ + - 防御器 - + + Defense Device + + + Save + Delete + Edit + Back + Loading... + Network error, please try again + Send + Submit + + + Smart Defense Device + SMS Login + Password Login + Enter phone number + Enter verification code + Enter password + Send Code + Login + Forgot Password? + + + Register + Register Account + Set Password + Confirm Password + Password must be 6–20 characters + I have read and agree to the + User Agreement + and + Privacy Policy + Registration Successful + Your account has been created successfully + Go to Login + + + Forgot Password + Reset Password + New Password + Password reset successful + + + Please align your face within the frame + Recognition Successful + Recognition Failed + Retry + + + Home + Profile + + + My Devices + Add Device + Scan QR Code + Voice Control + Light Control + Water Gun + Monitor + Message + Settings + + + Device Name + Status + Online + Device ID + Bind Device + Unbind Device + No devices found + + + Add Device + Scan Nearby Devices + Scanning continuously... + Please keep your phone close to the device + Scan Again + Add Manually + Enter Device ID + Binding Successful + + + Family Management + Switch Family + Current Family + My Family + Add Family + Family Name + Enter family name + Create Family + Join Family + Family Code + Enter family code + + + User Management + User List + Add User + Admin + Member + Phone Number + Enter nickname + + + Password Management + Change Password + Current Password + Old Password + Verification Code + + + Face Management + Add Face + Face List + Are you sure you want to delete this face? + Strict Capture + + + Live Video + Fullscreen + Screenshot + Record + Talk + Mute + Unmute + Loading video... + Video loading failed + + + Alarm Log + Alarm Detail + Alarm Time + Alarm Type + Location + No alarm records + Intrusion Detected + Abnormal Sound + Motion Detected + + + Messages + System + Alarm + Device + No messages + Mark as Read + Clear All + Message Detail + + + Settings + Function Settings + Voice Settings + Water Gun Settings + Detection Settings + Notification Settings + Language + Chinese + English + About + Version + Logout + Are you sure you want to logout? + + + Avatar + Gender + Male + Female + Birthday + Address + Enter address + + + Scan QR Code + Align QR code within frame to scan + Scan failed, please try again + + + WiFi List + WiFi Password + Enter WiFi password + Connect + Connecting... + Connection failed + Connected successfully + + + Tip + Please wait... + Operation successful + Operation failed + Network unavailable + Please check your network connection + + + Recognition Mode + Standard Mode + Strict Mode + Custom Mode + + + Today + Yesterday + This Week + This Month + + Hello blank fragment + + + Please scan the QR code on the device or manual + Workshop + Parents Home + Smart Hanging Defense + Smart Defense Device + Smart Rail Defense + Corridor Defense + Door Defense + Living Room Defense + Balcony Defense + Album + Flashlight + My Family + Device + Smart Defense Device A1 + Voice + Light + Control + %ds + Register + Register User + Enter Platform + Personal Info + Nickname + Enter nickname + Bind Phone + Face Recognition + Face Verification + Only used to create defense mechanisms and prevent theft, ensuring your security + Please follow the instructions to complete face verification + Standard Capture + Incomplete Capture + Insufficient Light + Start Verification + Select Wi-Fi + Enter Wi-Fi name + Next + Set Name + Enter device name + Complete + Alarm Log + Cancel + Confirm + Bluetooth Recognition + Bluetooth + Face Recognition + Messages + Face Collection + Please align your face within the circular area + Collect Face + Retrieve Password + Enter phone number + Enter verification code + Send Code + Enter new password + Enter password again + Confirm + ID Number + Enter ID number + Invite Code (Optional) + Enter invite code + Scan to Add + WiFi + Face Login + Recording permission is required for control features + Video ready + Playback complete + Cannot load video + View alarm log + Paused + Resume playback + Entered fullscreen + Exited fullscreen + Sound on + Sound off + Light on + Light off + Start control mode + Stop control mode + Recording start failed + Playback error: %1$d, %2$d + Buffering: %d%% + Camera not ready + Cannot open camera + Camera permission is required + Image selected + Please try again later + Invalid phone number format + Please enter verification code + Please get verification code first + Verification code error + Password cannot be empty + Password must contain both letters and digits + Passwords do not match + Redirecting to face page + Redirecting to register page + Forgot password page + Redirecting to face recognition page + Camera permission is required for face verification + Intrusion alarm + Device fault + Device offline + Renewal reminder + Someone invaded + Go check + Notice + Got it + Strike distance + Enter strike distance + Face detection failed + My nickname + Device has been running for %d days, please maintain in time + Device is offline, please check the WiFi and power connection + %ds retry + SMS login successful\nPhone: %1$s\nCode: %2$s + Password login successful\nPhone: %1$s\nPassword: %2$s + Verification code sent to %s + Login successful + Login successful \ No newline at end of file