Есть ли способ установить культуру для всего приложения? Все текущие и новые темы?

Есть ли способ установить культуру для всего приложения? Все текущие и новые темы?

У нас есть имя культуры, хранящееся в базе данных, и когда наше приложение запускается, мы делаем

CultureInfo ci = new CultureInfo(theCultureString);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;

Но, конечно, это «теряется», когда мы хотим сделать что-то в новом потоке. Есть ли способ настроить эти CurrentCulture и CurrentUICulture для всего приложения? Так что новые треды тоже приобретают эту культуру? Или это событие запускается всякий раз, когда создается новый поток, к которому я могу подключиться?

Если вы используете ресурсы, вы можете принудительно выполнить это вручную: Resource1.Culture = new System.Globalization.CultureInfo ("fr"); Таким образом, каждый раз, когда вы хотите получить строку, она локализуется и возвращается

Reza S 07.11.2011 23:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
175
1
165 426
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Об этом часто спрашивают. По сути, нет, не для .NET 4.0. Вы должны делать это вручную в начале каждого нового потока (или функции ThreadPool). Возможно, вы могли бы сохранить имя культуры (или просто объект культуры) в статическом поле, чтобы избежать попадания в БД, но это все.

немного раздражает ... кажется, ты прав, хе-хе. Итак, мы делаем это сейчас (и у нас есть культура как статический класс), но у нас все еще есть проблема с некоторыми потоками, которые мы не контролируем. Подобно обработке потоков в средстве просмотра отчетов Microsoft. Однако нашел обходной путь. Благодарю вас за информацию :)

Svish 23.01.2009 14:17

Это действительно раздражает: (Было бы неплохо, если бы существовал способ автоматически установить Current (UI) Culture для вашего приложения и позволить всем новым потокам использовать это значение.

Jedidja 03.09.2010 21:32

Я так давно с этим не работал, поэтому не помню точно, что мы делали. Но я думаю, могло случиться так, что вместо использования дат в наборе данных, отправленном средству просмотра отчетов, мы сначала отформатировали дату в строку, используя культуру, которую мы установили в приложении. Тогда уже не имело значения, что потоки рендеринга отчетов использовали неправильную культуру. Поэтому мы не обошли проблему с потоками, использующими неправильную культуру. Мы просто обошли проблему неправильного форматирования дат :)

Svish 01.07.2011 18:16

В нашем приложении я попытался «захватить» потоки (путем вызова специального метода из определенных мест) и сохранить их в коллекции для последующего использования (в данном случае для установки культуры), что, похоже, работает слишком далеко.

Mr. TA 01.07.2011 21:02

Не могли бы вы сохранить объект cultureinfo в сеансе и (если вы используете мастер-страницы) проверить его в выделенном коде мастер-страницы и установить текущий поток?

user609926 12.07.2016 17:14
Ответ принят как подходящий

В .NET 4.5 вы можете использовать свойство CultureInfo.DefaultThreadCurrentCulture для изменения культуры домена приложения.

Для версий до 4.5 вы должны использовать отражение для управления культурой домена приложения. На CultureInfo есть частное статическое поле (m_userDefaultCulture в mscorlib .NET 2.0, s_userDefaultCulture в mscorlib .NET 4.0), которое контролирует, что возвращает CurrentCulture, если поток не установил это свойство для себя.

Это не меняет локаль собственного потока, и, вероятно, не рекомендуется отправлять код, который изменяет культуру таким образом. Хотя это может быть полезно для тестирования.

Будьте осторожны с этим параметром в приложениях ASP.NET. Установка культуры в AppDomain установит культуру для всех пользователей. Так что англичанам не будет хорошо видеть, например, веб-сайт на немецком языке.

Dimitar Tsonev 20.03.2015 18:58

Я унаследовал приложение ASP.NET, которое работает только в том случае, если все культуры находятся в en-US. Это сценарий, в котором этот параметр идеально подходит на время, пока этот недостаток не будет исправлен.

Daniel Hilgarth 22.01.2016 17:00

Если вы используете ресурсы, вы можете заставить его вручную:

Resource1.Culture = new System.Globalization.CultureInfo("fr"); 

В диспетчере ресурсов есть автоматически сгенерированный код, который выглядит следующим образом:

/// <summary>
///   Overrides the current thread's CurrentUICulture property for all
///   resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
    get {
        return resourceCulture;
    }
    set {
        resourceCulture = value;
    }
}

Теперь каждый раз, когда вы ссылаетесь на свою отдельную строку в этом ресурсе, она переопределяет культуру (поток или процесс) с помощью указанной resourceCulture.

Вы можете указать язык как «fr», «de» и т. д. Или указать код языка как 0x0409 для en-US или 0x0410 для it-IT. Полный список языковых кодов см .: Идентификаторы языков и локали

Его можно "не применять принудительно", установив для него значение Null: Resource1.Culture = Null;.

habakuk 17.10.2016 17:23

На самом деле вы может устанавливаете культуру потока и культуру пользовательского интерфейса по умолчанию, но только с Framework 4.5+

Я вставил этот статический конструктор

static MainWindow()
{
  CultureInfo culture = CultureInfo
    .CreateSpecificCulture(CultureInfo.CurrentCulture.Name);
  var dtf = culture.DateTimeFormat;
  dtf.ShortTimePattern = (string)Microsoft.Win32.Registry.GetValue(
    "HKEY_CURRENT_USER\\Control Panel\\International", "sShortTime", "hh:mm tt");
  CultureInfo.DefaultThreadCurrentUICulture = culture;
}

и установите точку останова в методе Convert объекта ValueConverter, чтобы увидеть, что пришло на другой конец. CultureInfo.CurrentUICulture перестала быть en-US и вместо этого стала en-AU с моим небольшим хаком, чтобы заставить его уважать региональные настройки для ShortTimePattern.

Ура, в мире все хорошо! Или нет. Параметр культуры, переданный методу Convert, - по-прежнему en-US. Эмм, черт возьми ?! Но это только начало. По крайней мере так

  • вы можете исправить культуру пользовательского интерфейса один раз, когда ваше приложение загружается
  • он всегда доступен с CultureInfo.CurrentUICulture
  • string.Format("{0}", DateTime.Now) будет использовать ваши региональные настройки

Если вы не можете использовать версию 4.5 фреймворка, откажитесь от установки CurrentUICulture как статического свойства CultureInfo и установите его как статическое свойство одного из ваших собственных классов. Это не исправит поведение по умолчанию для string.Format или заставит StringFormat правильно работать в привязках, а затем пройти по логическому дереву вашего приложения, чтобы воссоздать все привязки в вашем приложении и установить их культуру конвертера.

Ответ Остина уже дал представление о том, что CultureInfo.DefaultThreadCurrentCulture можно настроить для изменения культуры домена приложения. CultureInfo.DefaultThreadCurrentUICulture относится к CurrentUICulture, а CultureInfo.DefaultThreadCurrentCulture - к CurrentCulture. На самом деле нет причин получать значение прямо из реестра в вашем коде. Если вы хотите изменить CurrentCulture на какую-то конкретную культуру, но сохранить переопределения пользователя, вам просто нужно получить значение из DateTimeFormat CurrentCulture, прежде чем переопределить его.

Eric MSFT 24.01.2014 03:34

Мне придется проверить, но я, кажется, помню, как пытался это сделать безуспешно, что привело к получению его из реестра. Вы действительно думаете, что я пошел бы на все эти проблемы без причины? Доступ к реестру - это гигантская PITA в этом дивном новом мире UAC.

Peter Wone 24.01.2014 08:12

DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture также присутствуют в Framework 4.0, но они являются частными. Используя Reflection, вы можете легко их настроить. Это повлияет на все потоки, для которых явно не установлен CurrentCulture (в том числе запущенные потоки).

Public Sub SetDefaultThreadCurrentCulture(paCulture As CultureInfo)
    Thread.CurrentThread.CurrentCulture.GetType().GetProperty("DefaultThreadCurrentCulture").SetValue(Thread.CurrentThread.CurrentCulture, paCulture, Nothing)
    Thread.CurrentThread.CurrentCulture.GetType().GetProperty("DefaultThreadCurrentUICulture").SetValue(Thread.CurrentThread.CurrentCulture, paCulture, Nothing)
End Sub

Этот сработал для меня. Хотя используется Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = культура; Что выглядит так же, не так. Для ясности это используется в приложении WPF, где само приложение меняло свою культуру, однако элементы управления в других проектах использовали культуру браузера, а не культуру, выбранную пользователем.

chillfire 08.12.2015 12:11

Для ASP.NET5, то есть ASPNETCORE, вы можете сделать следующее в configure:

app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture(new CultureInfo("en-gb")),
    SupportedCultures = new List<CultureInfo>
    {
        new CultureInfo("en-gb")
    },
            SupportedUICultures = new List<CultureInfo>
    {
        new CultureInfo("en-gb")
    }
});

Вот серия сообщений в блоге, который дает больше информации.

Я искал способ сделать это на устаревшем сайте ASP.NET 2.0, и меня разочаровывает, насколько легко я справился с этим с другим сайтом Core по сравнению с этим! Я работаю в многонациональной компании, и для внутренних сайтов все наше форматирование выполняется в формате en-US, чтобы избежать путаницы с датами. Но этот устаревший сайт настроен для en-US, en-CA и fr-CA. И в некотором смысле "хакерский", поэтому, когда я пытаюсь исправить это, все их преобразования типов взрываются на уровне данных! (Французская денежная оценка: "1 234,56 $"

Andrew S 04.10.2017 18:28

@Sean, ваша ссылка не работает. Может это указывает на это, это и это

Fer R 29.05.2018 20:03

Вот решение для C# MVC:

  1. Во-первых: создайте настраиваемый атрибут и переопределите метод следующим образом:

    public class CultureAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Retreive culture from GET
            string currentCulture = filterContext.HttpContext.Request.QueryString["culture"];
    
            // Also, you can retreive culture from Cookie like this :
            //string currentCulture = filterContext.HttpContext.Request.Cookies["cookie"].Value;
    
            // Set culture
            Thread.CurrentThread.CurrentCulture = new CultureInfo(currentCulture);
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(currentCulture);
        }
    }
    
  2. Во-вторых: в App_Start найдите FilterConfig.cs, добавьте этот атрибут. (это работает для ВСЕГО приложения)

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // Add custom attribute here
            filters.Add(new CultureAttribute());
        }
    }    
    

Это оно !

Если вы хотите определить культуру для каждого контроллера / действия вместо всего приложения, вы можете использовать этот атрибут следующим образом:

[Culture]
public class StudentsController : Controller
{
}

Или же:

[Culture]
public ActionResult Index()
{
    return View();
}

Для .NET 4.5 и выше вы должны использовать:

var culture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;

Этот ответ является небольшим расширением отличного ответа @rastating. Вы можете без проблем использовать следующий код для всех версий .NET:

    public static void SetDefaultCulture(CultureInfo culture)
    {
        Type type = typeof (CultureInfo);
        try
        {
            // Class "ReflectionContext" exists from .NET 4.5 onwards.
            if (Type.GetType("System.Reflection.ReflectionContext", false) != null)
            {
                type.GetProperty("DefaultThreadCurrentCulture")
                    .SetValue(System.Threading.Thread.CurrentThread.CurrentCulture,
                        culture, null);

                type.GetProperty("DefaultThreadCurrentUICulture")
                    .SetValue(System.Threading.Thread.CurrentThread.CurrentCulture,
                        culture, null);
            }
            else //.NET 4 and lower
            {
                type.InvokeMember("s_userDefaultCulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});

                type.InvokeMember("s_userDefaultUICulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});

                type.InvokeMember("m_userDefaultCulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});

                type.InvokeMember("m_userDefaultUICulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});
            }
        }
        catch
        {
            // ignored
        }
    }
}

Рабочее решение для установки CultureInfo для всех потоков и окон.

  1. Откройте файл App.xaml и добавьте новый атрибут «Запуск», чтобы назначить обработчик событий запуска для приложения:
<Application ........
             Startup = "Application_Startup"
>
  1. Откройте файл App.xaml.cs и добавьте этот код в созданный обработчик запуска (в данном случае Application_Startup). Приложение класса будет выглядеть так:
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-US");
            System.Globalization.CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
            System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
            Thread.CurrentThread.CurrentCulture = cultureInfo;
        }
    }

Другие вопросы по теме