区域设置子系统(CategoryLocale)
SDL 提供了轻量的区域设置服务,核心能力是获取用户的首选区域列表(由「语言 + 国家/地区」组成)。该子系统仅包含一个核心函数:SDL_GetPreferredLocales(),它会自动处理不同系统、不同配置方式下的语言设置解析,兼容各类复杂的用户语言配置场景(如多语言优先级、地区变体等)。
这一功能是实现应用多语言适配的基础——通过获取用户的首选语言,应用可自动切换界面文本、音频、字体等资源,提升本地化体验。
函数
- SDL_GetPreferredLocales:获取用户的首选区域设置列表,返回 SDL_Locale 结构体数组(数组末尾以 NULL 结尾);函数内部自动分配内存,调用者需通过 SDL_free() 释放整个数组
数据类型
- (无)
结构体
- SDL_Locale:区域设置结构体,包含两个核心字段:
- language:语言代码(符合 ISO 639 标准,如 "zh" 表示中文、"en" 表示英文、"ja" 表示日文)
- country:国家/地区代码(符合 ISO 3166 标准,如 "CN" 表示中国、"US" 表示美国、"TW" 表示中国台湾);若未指定地区,该字段为 NULL
枚举
- (无)
宏
- (无)
FreeBASIC 示例代码
' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库)
#Include "SDL.bi"
' 补充结构体和函数声明(FreeBASIC 绑定可能缺失)
Type SDL_Locale
language As ZString Ptr ' 语言代码(如 "zh"、"en")
country As ZString Ptr ' 国家/地区代码(如 "CN"、"US",NULL 表示未指定)
End Type
Declare Function SDL_GetPreferredLocales CDecl () As SDL_Locale Ptr
Declare Sub SDL_free CDecl (ByVal ptr As Any Ptr)
' 打印区域设置信息
Sub PrintLocaleInfo(ByVal locale As SDL_Locale Ptr)
If (locale = NULL) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - 无区域信息")
Exit Sub
End If
' 拼接语言+地区字符串(如 "zh-CN"、"en-US")
Dim As ZString * 32 localeStr
If (locale->country <> NULL) Then
snprintf(@localeStr, sizeof(localeStr), "%s-%s", *locale->language, *locale->country)
Else
snprintf(@localeStr, sizeof(localeStr), "%s", *locale->language)
End If
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - %s", localeStr)
' 补充语言/地区说明
If (strcmp(locale->language, "zh") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:中文")
If (locale->country <> NULL) Then
If (strcmp(locale->country, "CN") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国大陆")
ElseIf (strcmp(locale->country, "TW") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国台湾")
ElseIf (strcmp(locale->country, "HK") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国香港")
End If
End If
ElseIf (strcmp(locale->language, "en") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:英文")
If (locale->country <> NULL And strcmp(locale->country, "US") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:美国")
ElseIf (locale->country <> NULL And strcmp(locale->country, "GB") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:英国")
End If
ElseIf (strcmp(locale->language, "ja") = 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:日文")
End If
End Sub
' 获取并解析用户首选区域列表
Sub GetPreferredLocalesExample()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【获取用户首选区域设置】")
' 1. 获取首选区域列表(SDL 自动分配内存)
Dim As SDL_Locale Ptr locales = SDL_GetPreferredLocales()
If (locales = NULL) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "获取区域设置失败:%s", SDL_GetError())
Exit Sub
End If
' 2. 遍历并打印所有区域设置(数组以 NULL 结尾)
Dim As Integer i = 0
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户首选区域列表(按优先级排序):")
While (locales[i].language <> NULL)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "第 %d 项:", i + 1)
PrintLocaleInfo(@locales[i])
i += 1
Wend
If (i = 0) Then
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未获取到任何区域设置")
End If
' 3. 释放 SDL 分配的内存(必须调用,避免内存泄漏)
SDL_free(locales)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "区域设置内存已释放")
End Sub
' 根据区域设置选择应用语言
Sub SelectAppLanguage()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【根据区域设置选择应用语言】")
Dim As SDL_Locale Ptr locales = SDL_GetPreferredLocales()
If (locales = NULL) Then
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "使用默认语言:英文")
Exit Sub
End If
' 遍历首选区域列表,匹配支持的语言
Dim As ZString Ptr appLang = StrPtr("en") ' 默认语言:英文
Dim As Integer i = 0
While (locales[i].language <> NULL)
' 检查是否支持该语言
If (strcmp(locales[i].language, "zh") = 0) Then
appLang = StrPtr("zh")
' 进一步区分简繁(根据地区)
If (locales[i].country <> NULL) Then
If (strcmp(locales[i].country, "TW") = 0 Or strcmp(locales[i].country, "HK") = 0) Then
appLang = StrPtr("zh-TW") ' 繁体中文
Else
appLang = StrPtr("zh-CN") ' 简体中文
End If
End If
Exit While ' 匹配到首选语言,停止遍历
ElseIf (strcmp(locales[i].language, "ja") = 0) Then
appLang = StrPtr("ja") ' 日文
Exit While
End If
i += 1
Wend
' 输出选择结果
Select Case *appLang
Case "zh-CN": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:简体中文")
Case "zh-TW": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:繁体中文")
Case "ja": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:日文")
Case Else: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:英文(默认)")
End Select
' 释放内存
SDL_free(locales)
End Sub
' 主程序
Sub Main()
' 初始化 SDL(Locale 子系统无需特定子系统,基础初始化即可)
If (SDL_Init(0) < 0) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError())
Exit Sub
End If
' 运行示例
GetPreferredLocalesExample()
SelectAppLanguage()
' 清理 SDL
SDL_Quit()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出")
End Sub
' 运行主程序
Main()
核心知识点补充
-
区域代码规范:
- 语言代码遵循 ISO 639-1(两位小写,如
zh=中文、en=英文、fr=法语); - 地区代码遵循 ISO 3166-1 alpha-2(两位大写,如
CN=中国、US=美国、JP=日本); - 组合格式为
语言-地区(如zh-CN=简体中文(中国大陆)、en-US=美式英语、zh-TW=繁体中文(中国台湾))。
- 语言代码遵循 ISO 639-1(两位小写,如
-
平台实现逻辑: 平台 获取语言设置的原生方式 SDL 封装优势 Windows GetUserPreferredUILanguages 自动处理多语言优先级、兼容旧系统版本 macOS CFLocaleCopyPreferredLanguages 统一返回格式,无需处理 CoreFoundation 类型 Linux 读取 LANG/LC_* 环境变量 解析复杂的 locale 字符串(如 zh_CN.UTF-8)移动平台 Android: getResources().getConfiguration()
iOS: NSLocale跨平台统一返回 SDL_Locale 结构体 -
内存管理注意:
SDL_GetPreferredLocales()返回的数组由 SDL 分配内存,必须调用SDL_free()释放,否则会导致内存泄漏;- 数组内的
language/country字符串是数组内存的一部分,无需单独释放; - 数组以
language = NULL的元素结尾,遍历需以此为终止条件。
-
常见区域设置示例: 区域字符串 含义 应用适配建议 zh-CN 简体中文(中国大陆) 使用简体中文字体、简体文本资源 zh-TW 繁体中文(中国台湾) 使用繁体中文字体、繁体文本资源 en-US 美式英语 使用美式拼写(如 color/center) en-GB 英式英语 使用英式拼写(如 colour/centre) ja-JP 日文(日本) 使用日文字体、日文文本资源
总结
-
核心优势:
- 跨平台统一的区域设置获取接口,无需适配不同系统的原生语言 API;
- 自动解析复杂的系统语言配置,返回标准化的「语言+地区」格式;
- 轻量易用,仅一个核心函数即可完成所有逻辑,降低本地化开发成本。
-
使用建议:
- 应用启动时调用
SDL_GetPreferredLocales(),优先匹配用户首选语言; - 按优先级遍历区域列表,匹配到支持的语言后立即停止(无需遍历全部);
- 必须调用
SDL_free()释放返回的数组,避免内存泄漏; - 对未匹配到的语言,默认使用英文(或应用核心语言)保证可用性。
- 应用启动时调用
-
关键点回顾:
SDL_GetPreferredLocales()是区域设置子系统的唯一核心函数,返回按优先级排序的 SDL_Locale 数组;- SDL_Locale 包含
language(语言代码)和country(地区代码)两个字段,地区代码可能为 NULL; - 返回的数组必须通过
SDL_free()释放,这是避免内存泄漏的关键; - 区域设置是应用本地化的基础,需结合文本资源、字体、格式适配等功能使用。
评论一下?