Token导航 LogoToken导航

Agent Skill · 研究检索

localization-globalization(本地化全球化)

localization-globalization 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

localization-globalization 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 62,001。

总安装 343周安装 14GitHub Stars 15下载 110核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:localization-globalization(本地化全球化)
来源仓库:https://github.com/wshaddix/dotnet-skills
仓库路径:skills/localization-globalization
安装命令:
npx skills add https://github.com/wshaddix/dotnet-skills --skill localization-globalization
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/wshaddix/dotnet-skills --skill localization-globalization

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

localization-globalization 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。适用于多语言内容适配、跨市场信息整合及全球化项目中的本地化资源搜索等场景。

通过关键词匹配和来源仓库筛选,帮助 Agent 快速获取相关文档、配置或代码片段。安装命令为 npx skills add https://github.com/wshaddix/dotnet-skills --skill localization-globalization。

使用前需确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写操作。

来源仓库内路径:skills/localization-globalization

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/wshaddix/dotnet-skills --skill localization-gl…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

localization-globalization 怎么安装?

在终端执行 npx skills add https://github.com/wshaddix/dotnet-skills --skill localization-globalizatio…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

localization-globalization 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

localization-globalization 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

localization-globalization 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

localization-globalization 用的人多吗?

公开数据是累计安装 343 次,近一周安装 14 次,下载 110 次,GitHub 15 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

localization-globalization 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
localization-globalization

本地化全球化 · 本页

34315需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Rationale

Global applications require support for multiple languages, cultures, and formatting conventions. Poor localization implementation leads to maintenance nightmares, inconsistent user experiences, and hard-to-find bugs with dates, numbers, and currencies. These patterns provide a maintainable approach to building truly global Razor Pages applications.

Patterns

Pattern 1: Resource File Structure

Organize resources by feature with proper naming conventions and culture hierarchy.

/Pages
  /Shared
    _Layout.cshtml
    Resources/
      _Layout.resx          (default/en)
      _Layout.es.resx       (Spanish)
      _Layout.fr.resx       (French)
      _Layout.de.resx       (German)
  /Account
    Login.cshtml
    Login.cshtml.cs
    Resources/
      Login.resx
      Login.es.resx
      Login.fr.resx
  /Products
    Index.cshtml
    Resources/
      Index.resx
      Index.es.resx
/Resources  (Shared resources)
  SharedResources.resx
  SharedResources.es.resx
  ValidationMessages.resx
// SharedResources.cs - Type-safe resource access
public class SharedResources
{
    // This class is just a marker for IStringLocalizer<SharedResources>
}

// Strongly-typed resources with code generator
public static class ResourceKeys
{
    public const string WelcomeMessage = "WelcomeMessage";
    public const string SaveButton = "SaveButton";
    public const string CancelButton = "CancelButton";
    public const string ErrorOccurred = "ErrorOccurred";
    public const string RequiredField = "RequiredField";
}

Pattern 2: Localization Configuration

Configure request localization with proper culture detection and fallback.

// Program.cs
var supportedCultures = new[]
{
    new CultureInfo("en-US"),
    new CultureInfo("en-GB"),
    new CultureInfo("es-ES"),
    new CultureInfo("es-MX"),
    new CultureInfo("fr-FR"),
    new CultureInfo("de-DE")
};

builder.Services.AddLocalization(options =>
{
    options.ResourcesPath = "Resources";
});

builder.Services.AddRequestLocalization(options =>
{
    options.DefaultRequestCulture = new RequestCulture("en-US");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    // Culture detection order:
    // 1. Query string (?culture=es-ES)
    // 2. Cookie (.AspNetCore.Culture)
    // 3. Accept-Language header
    // 4. Default culture
    options.RequestCultureProviders = new List<IRequestCultureProvider>
    {
        new QueryStringRequestCultureProvider(),
        new CookieRequestCultureProvider(),
        new AcceptLanguageHeaderRequestCultureProvider()
    };
});

// Register view localization
builder.Services.AddRazorPages()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization(options =>
    {
        options.DataAnnotationLocalizerProvider = (type, factory) =>
            factory.Create(typeof(SharedResources));
    });

// Middleware placement (must be before routing)
var app = builder.Build();
app.UseRequestLocalization();
app.UseRouting();
app.MapRazorPages();

Pattern 3: Razor Pages Localization

Implement view and PageModel localization with proper resource injection.

// PageModel with localization
public class ProductEditModel : PageModel
{
    private readonly IStringLocalizer<ProductEditModel> _localizer;
    private readonly IStringLocalizer<SharedResources> _sharedLocalizer;
    private readonly ILogger<ProductEditModel> _logger;

    public ProductEditModel(
        IStringLocalizer<ProductEditModel> localizer,
        IStringLocalizer<SharedResources> sharedLocalizer,
        ILogger<ProductEditModel> logger)
    {
        _localizer = localizer;
        _sharedLocalizer = sharedLocalizer;
        _logger = logger;
    }

    [BindProperty]
    public ProductInput Input { get; set; } = new();

    public string PageTitle => _localizer["EditProductTitle"];

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        try
        {
            await SaveProductAsync(Input);

            TempData["SuccessMessage"] = _localizer["ProductSaved"];
            return RedirectToPage("/Products/Index");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to save product");
            ModelState.AddModelError(string.Empty, _sharedLocalizer["ErrorOccurred"]);
            return Page();
        }
    }
}

// View with localization
@page "{id:guid}"
@model ProductEditModel
@inject IStringLocalizer<SharedResources> SharedLocalizer
@inject IViewLocalizer ViewLocalizer

@{
    ViewData["Title"] = Model.PageTitle;
}

<h1>@ViewLocalizer["EditProductTitle"]</h1>

<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    <div class="form-group">
        <label asp-for="Input.Name">@ViewLocalizer["ProductName"]</label>
        <input asp-for="Input.Name" class="form-control"
               placeholder="@ViewLocalizer["NamePlaceholder"]" />
        <span asp-validation-for="Input.Name" class="text-danger"></span>
    </div>

    <div class="form-group">
        <label asp-for="Input.Price">@ViewLocalizer["Price"]</label>
        <input asp-for="Input.Price" class="form-control"
               type="number" step="0.01" />
        <small class="form-text text-muted">
            @ViewLocalizer["PriceHelpText"]
        </small>
    </div>

    <button type="submit" class="btn btn-primary">
        @SharedLocalizer["SaveButton"]
    </button>
    <a asp-page="/Products/Index" class="btn btn-secondary">
        @SharedLocalizer["CancelButton"]
    </a>
</form>

Pattern 4: Culture-Specific Formatting

Use culture-aware formatting for dates, numbers, and currencies.

// Extension methods for consistent formatting
public static class FormattingExtensions
{
    public static string ToCurrency(this decimal amount, IFormatProvider? provider = null)
    {
        return amount.ToString("C", provider ?? CultureInfo.CurrentCulture);
    }

    public static string ToShortDate(this DateTime date, IFormatProvider? provider = null)
    {
        return date.ToString("d", provider ?? CultureInfo.CurrentCulture);
    }

    public static string ToLongDate(this DateTime date, IFormatProvider? provider = null)
    {
        return date.ToString("D", provider ?? CultureInfo.CurrentCulture);
    }

    public static string ToCompactNumber(this int number, IFormatProvider? provider = null)
    {
        return number.ToString("N0", provider ?? CultureInfo.CurrentCulture);
    }
}

// View usage
@inject IStringLocalizer<SharedResources> Localizer

<div class="product-details">
    <p>@Localizer["PriceLabel"]: @Model.Product.Price.ToCurrency()</p>
    <p>@Localizer["AvailableFrom"]: @Model.Product.AvailableDate.ToLongDate()</p>
    <p>@Localizer["StockQuantity"]: @Model.Product.Stock.ToCompactNumber()</p>
</div>

// Culture-specific validation messages
public class ProductInput
{
    [Required(ErrorMessageResourceName = "RequiredField",
              ErrorMessageResourceType = typeof(SharedResources))]
    [StringLength(100, ErrorMessageResourceName = "MaxLength",
                  ErrorMessageResourceType = typeof(SharedResources))]
    public required string Name { get; set; }

    [Range(0.01, 999999.99, ErrorMessageResourceName = "InvalidPrice",
           ErrorMessageResourceType = typeof(SharedResources))]
    [DataType(DataType.Currency)]
    public decimal Price { get; set; }

    [DataType(DataType.Date)]
    [Display(ResourceType = typeof(SharedResources), Name = "AvailableDateLabel")]
    public DateTime AvailableDate { get; set; }
}

Pattern 5: Language Switcher Implementation

Create a language switcher that persists culture selection.

// Culture controller for switching languages
public class CultureController : Controller
{
    [HttpPost]
    public IActionResult SetCulture(string culture, string returnUrl)
    {
        if (!string.IsNullOrEmpty(culture))
        {
            Response.Cookies.Append(
                CookieRequestCultureProvider.DefaultCookieName,
                CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
                new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
            );
        }

        return LocalRedirect(returnUrl ?? "/");
    }
}

// Language switcher partial view (_LanguageSwitcher.cshtml)
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>()!;
    var cultureItems = LocOptions.Value.SupportedUICultures!
        .Select(c => new SelectListItem {
            Value = c.Name,
            Text = c.DisplayName,
            Selected = c.Name == requestCulture.RequestCulture.UICulture.Name
        })
        .ToList();
    var returnUrl = string.IsNullOrEmpty(Context.Request.Path)
        ? "~/"
        : $"~{Context.Request.Path.Value}{Context.Request.QueryString}";
}

<form asp-controller="Culture" asp-action="SetCulture"
      asp-route-returnUrl="@returnUrl" method="post"
      class="form-inline">
    <select name="culture"
            class="form-control form-control-sm"
            onchange="this.form.submit();"
            asp-for="@requestCulture.RequestCulture.UICulture.Name"
            asp-items="cultureItems">
    </select>
</form>

// Include in _Layout.cshtml
<div class="navbar-nav">
    <partial name="_LanguageSwitcher" />
</div>

Pattern 6: Pluralization and Complex Strings

Handle pluralization and parameterized strings correctly.

// Using Humanizer for pluralization
public static class LocalizationHelpers
{
    public static string FormatItemsCount(IStringLocalizer localizer, int count)
    {
        var key = count switch
        {
            0 => "ItemsCountZero",
            1 => "ItemsCountOne",
            _ => "ItemsCountMany"
        };

        return localizer[key, count];
    }

    public static string FormatTimeRemaining(IStringLocalizer localizer, TimeSpan time)
    {
        if (time.TotalDays >= 1)
            return localizer["DaysRemaining", (int)time.TotalDays];
        if (time.TotalHours >= 1)
            return localizer["HoursRemaining", (int)time.TotalHours];
        if (time.TotalMinutes >= 1)
            return localizer["MinutesRemaining", (int)time.TotalMinutes];

        return localizer["LessThanMinute"];
    }
}

// Resource file entries
// ItemsCountZero: "No items"
// ItemsCountOne: "One item"
// ItemsCountMany: "{0} items"
// DaysRemaining: "{0} days remaining"
// HoursRemaining: "{0} hours remaining"
// MinutesRemaining: "{0} minutes remaining"
// LessThanMinute: "Less than a minute"

// View usage
<p>@LocalizationHelpers.FormatItemsCount(Localizer, Model.Items.Count)</p>
<p>@LocalizationHelpers.FormatTimeRemaining(Localizer, Model.TimeRemaining)</p>

Pattern 7: RTL (Right-to-Left) Support

Support RTL languages like Arabic and Hebrew with proper CSS and layout.

// View component for RTL detection
public class RtlLayoutViewComponent : ViewComponent
{
    private static readonly string[] RtlCultures = { "ar", "he", "fa", "ur" };

    public IViewComponentResult Invoke()
    {
        var currentCulture = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
        var isRtl = RtlCultures.Contains(currentCulture);

        return View(isRtl);
    }
}

// _Layout.cshtml modifications
@inject IViewLocalizer Localizer

@{
    var isRtl = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft;
    var dir = isRtl ? "rtl" : "ltr";
}

<!DOCTYPE html>
<html lang="@CultureInfo.CurrentCulture.TwoLetterISOLanguageName" dir="@dir">
<head>
    @if (isRtl)
    {
        <link rel="stylesheet" href="~/css/bootstrap.rtl.min.css" />
        <link rel="stylesheet" href="~/css/site.rtl.css" />
    }
    else
    {
        <link rel="stylesheet" href="~/css/bootstrap.min.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    }
</head>
<body>
    <!-- Content -->
</body>
</html>

// CSS with logical properties (works for both LTR and RTL)
.sidebar {
    margin-inline-start: 1rem; /* Replaces margin-left */
    padding-inline-end: 0.5rem; /* Replaces padding-right */
    border-inline-start: 1px solid #ddd;
}

Anti-Patterns

// ❌ BAD: Hard-coded strings
public string GetMessage() => "Hello, World!";

// ✅ GOOD: Use localizer
public string GetMessage() => _localizer["HelloWorld"];

// ❌ BAD: Concatenating strings for pluralization
var message = $"You have {count} item{(count != 1 ? "s" : "")}";

// ✅ GOOD: Use resource keys for each case
var message = count switch
{
    0 => _localizer["NoItems"],
    1 => _localizer["OneItem"],
    _ => _localizer["ManyItems", count]
};

// ❌ BAD: Formatting without culture
var price = $"${amount:F2}"; // Wrong currency symbol, wrong format

// ✅ GOOD: Culture-aware formatting
var price = amount.ToString("C", CultureInfo.CurrentCulture);

// ❌ BAD: Storing culture in session
HttpContext.Session.SetString("Culture", "es-ES"); // Not thread-safe

// ✅ GOOD: Use built-in cookie or query string providers
Response.Cookies.Append(
    CookieRequestCultureProvider.DefaultCookieName,
    CookieRequestCultureProvider.MakeCookieValue(new RequestCulture("es-ES")));

// ❌ BAD: Not providing fallback resources
// Only es-ES.resx exists, user requests es-MX

// ✅ GOOD: Provide neutral culture resources
// es.resx (neutral) + es-ES.resx (specific) + es-MX.resx (specific)

// ❌ BAD: Loading all resources on startup
foreach (var culture in supportedCultures)
{
    var resources = LoadResourcesForCulture(culture); // Expensive!
}

// ✅ GOOD: Let ASP.NET Core lazy-load resources as needed

// ❌ BAD: Mixing UI culture and data culture
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");    // Numbers/dates
Thread.CurrentThread.CurrentUICulture = new CultureInfo("es-ES");  // Resources

// ✅ GOOD: Usually keep them in sync unless you have specific requirements
var culture = new CultureInfo(userPreferredLanguage);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;

// ❌ BAD: Not validating culture codes
public void SetCulture(string culture)
{
    CultureInfo.CurrentCulture = new CultureInfo(culture); // Throws on invalid!
}

// ✅ GOOD: Validate against supported cultures
public bool TrySetCulture(string cultureCode)
{
    var culture = supportedCultures.FirstOrDefault(c =>
        c.Name.Equals(cultureCode, StringComparison.OrdinalIgnoreCase));

    if (culture is null) return false;

    CultureInfo.CurrentCulture = culture;
    CultureInfo.CurrentUICulture = culture;
    return true;
}

References

平台分布

Codex

38.25%
按下载量换算42

Claude

32.46%
按下载量换算36

Cursor

17.24%
按下载量换算19

Gemini CLI

9.14%
按下载量换算10

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills