⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vcue_locale.h

📁 Vc.Net入门与提高源码
💻 H
字号:
// VCUE_Locale.h
// (c) 2000 Microsoft Corporation
//
//////////////////////////////////////////////////////////////////////
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Classes Reference and related electronic
// documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft C++ Libraries products.

#if !defined(_VCUE_LOCALE_H___23343755_6CE2_4026_BE11_4488555CD8B3___INCLUDED_)
#define _VCUE_LOCALE_H___23343755_6CE2_4026_BE11_4488555CD8B3___INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "VCUE_Accept.h"
#include "VCUE_ServerContext.h"

namespace VCUE
{
	// Exact matching
	//			"en"	"en-gb"		"en-us"
	//	"en"	  1		   0		   0
	//	"en-gb"	  0		   1		   0
	//	"en-us"	  0		   0		   1
	//
	// Asymmetric matching
	//			"en"	"en-gb"		"en-us"
	//	"en"	  1		   0		   0
	//	"en-gb"	  1		   1		   0
	//	"en-us"	  1		   0		   1
	//
	// Symmetric matching
	//			"en"	"en-gb"		"en-us"
	//	"en"	  1		   1		   1
	//	"en-gb"	  1		   1		   0
	//	"en-us"	  1		   0		   1
	//
	// Primary matching
	//			"en"	"en-gb"		"en-us"
	//	"en"	  1		   1		   1
	//	"en-gb"	  1		   1		   1
	//	"en-us"	  1		   1		   1

	// LanguageMatch
	//			"en"	"en-gb"		"en-us"		*
	//	"en"	  e		   s		   s		p
	//	"en-gb"	  a		   e		   p		p
	//	"en-us"	  a		   p		   e		p

	enum LanguageMatchType { lmNoMatch = 0, lmPrimary, lmSymmetric, lmAsymmetric, lmExact};

	// Use this function to determine whether HTTP language tags match.
	inline LanguageMatchType LanguageMatch(const char* pszLanguage1, const char* pszLanguage2) throw()
	{
		ATLASSERT(pszLanguage1);
		ATLASSERT(pszLanguage2);

		if (*pszLanguage1 == '*' || *pszLanguage2 == '*')
			return lmPrimary;

		while (*pszLanguage1 && *pszLanguage2 && *pszLanguage1 != '-' && *pszLanguage2 != '-')
		{
			if (*pszLanguage1 != *pszLanguage2)
				return lmNoMatch;
			++pszLanguage1;
			++pszLanguage2;
		}

		if ((*pszLanguage1 == '\0') && (*pszLanguage2 == '\0'))
			return lmExact;

		if ((*pszLanguage1 == '\0') && (*pszLanguage2 == '-'))
			return lmAsymmetric;

		if ((*pszLanguage1 == '-') && (*pszLanguage2 == '\0'))
			return lmSymmetric;

		while (*pszLanguage1 && *pszLanguage2)
		{
			if (*pszLanguage1 != *pszLanguage2)
				return lmPrimary;

			++pszLanguage1;
			++pszLanguage2;
		}

		if ((*pszLanguage1 == '\0') && (*pszLanguage2 == '\0'))
			return lmExact;

		return lmNoMatch;
	}

	class CUserLocale
	{
	private:
		// This is the closest locale supported by the server that matches one of the 
		// languages specified by the client's Accept-Language request header.
		// Use this locale for keying into predefined content.
		LCID m_lcidServer;

		// This is the locale specified by the client's Accept-Language request header
		// that corresponds to the locale in lcidServer.
		// Use this locale for dynamically generated content (formatting dates, times, currencies, etc.)
		LCID m_lcidClient;

		// In many cases, lcidServer and lcidClient will be identical.
		// In some cases, one locale may be more generic than the other
		// (e.g. lcidServer could be the default English locale, lcidClient could be US English)
		// Be careful mixing predefined content with dynamically generated content if you decide
		// to use different locales.
	public:
		CUserLocale(LCID lcidServer = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT))
			: m_lcidServer(lcidServer), m_lcidClient(lcidServer) {}

		CUserLocale(LCID lcidServer, LCID lcidClient)
			: m_lcidServer(lcidServer), m_lcidClient(lcidClient) {}

		LCID GetServerLocale() const throw()
		{
			return m_lcidServer;
		}

		bool SetServerLocale(LCID lcid) throw()
		{
			m_lcidServer = lcid;
			return true;
		}

		LCID GetClientLocale() const throw()
		{
			return m_lcidClient;
		}

		bool SetClientLocale(LCID lcid) throw()
		{
			m_lcidClient = lcid;
			return true;
		}

		LCID GetLocale() const throw()
		{
			return m_lcidServer;
		}

		bool SetLocale(LCID lcid) throw()
		{
			m_lcidServer = lcid;
			m_lcidClient = lcid;
			return true;
		}

		bool SetDefaultEnglishLocale() throw()
		{
			return SetLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT));
		}
	};

	
	inline LanguageMatchType GetUserLocale(IMultiLanguage* pMultiLanguage, const char* arrSupportedLanguages[], const char* pszClientLanguage, CUserLocale& theLocale) throw()
	{
		ATLASSERT(pMultiLanguage);

		// These vars ensure that we don't change theLocale unless everything succeeds.
		LCID lcidClient = 0;
		LCID lcidServer = 0;

		// Get the client locale from the multi-language object
		HRESULT hr = pMultiLanguage->GetLcidFromRfc1766(&lcidClient, CComBSTR(pszClientLanguage));
		if (SUCCEEDED(hr))
		{
			const char** ppsz = arrSupportedLanguages;
			
			const char* pszBestMatch = NULL;
			LanguageMatchType matchBest = lmNoMatch;

			while (*ppsz)
			{
				LanguageMatchType matchCurrent = LanguageMatch(pszClientLanguage, *ppsz);
				if (matchCurrent > matchBest)	// Update match if better than current
				{
					matchBest = matchCurrent;
					pszBestMatch = *ppsz;
				}

				if (lmExact == matchBest)		// Stop now if we have exact match
				{
					if (SUCCEEDED(pMultiLanguage->GetLcidFromRfc1766(&lcidServer, CComBSTR(pszBestMatch))))
					{
						theLocale.SetClientLocale(lcidClient);
						theLocale.SetServerLocale(lcidServer);
						return matchBest;
					}
				}

				++ppsz;
			}

			if (lmNoMatch != matchBest)
			{
				if (SUCCEEDED(pMultiLanguage->GetLcidFromRfc1766(&lcidServer, CComBSTR(pszBestMatch))))
				{
					theLocale.SetClientLocale(lcidClient);
					theLocale.SetServerLocale(lcidServer);
					return matchBest;
				}
			}
		}

		return lmNoMatch;
	}

	inline LanguageMatchType GetUserLocale(IMultiLanguage* pMultiLanguage, const char* arrSupportedLanguages[], IHttpServerContext* pServerContext, CAcceptCollection& languages, CUserLocale& theLocale /*, LanguageMatchType matchTerminator = lmAsymmetric*/) throw()
	{
		LanguageMatchType matchBest = lmNoMatch;
		CUserLocale localeBest;

		CStringA strAccept;
		BOOL bSuccess = GetServerVariable(pServerContext, "HTTP_ACCEPT_LANGUAGE", strAccept);
		if (bSuccess && strAccept.GetLength())
		{
			languages.Parse(strAccept);

			// Languages are ordered with user's favorites first
			// Languages with a priority of zero are disallowed
			if (languages.GetCount())
			{
				POSITION pos = languages.GetHeadPosition();
				while (pos)
				{
					const CAcceptItem& item = languages.GetNext(pos);
					if (!item.GetPriority())
						break;

					LanguageMatchType matchCurrent = GetUserLocale(pMultiLanguage, arrSupportedLanguages, item.GetValue(), theLocale);
					if (matchCurrent >= lmPrimary) // TODO - consider comparing against lmAsymmetric or exposing termination condition as a parameter
						return matchCurrent;

					if (matchCurrent > matchBest)
					{
						matchBest = matchCurrent;
						localeBest = theLocale;
					}
				}
			}
		}

		if (lmNoMatch != matchBest)
		{
			theLocale = localeBest;
		}

		return matchBest;
	}

	inline LanguageMatchType GetUserLocale(const char* arrSupportedLanguages[], IHttpServerContext* pServerContext, CUserLocale& theLocale /*, LanguageMatchType matchTerminator = lmAsymmetric*/) throw()
	{
		// Consider calling a different overload if you need to reuse the multilanguage
		// object or the collection of languages from the Accept-Language request header.
		CComPtr<IMultiLanguage> spMultiLanguage;
		HRESULT hr = spMultiLanguage.CoCreateInstance(__uuidof(CMultiLanguage));
		if (FAILED(hr))
			return lmNoMatch;

		CAcceptCollection languages;
		return GetUserLocale(spMultiLanguage, arrSupportedLanguages, pServerContext, languages, theLocale/*, matchTerminator*/);
	}

	inline int UnicodeToUtf8(const CStringW& strUnicode, CStringA& strUtf8)
	{
		int nCharacters = AtlUnicodeToUTF8(strUnicode, strUnicode.GetLength(), NULL, 0);
		char* szBuffer = strUtf8.GetBufferSetLength(nCharacters + 1);
		nCharacters = AtlUnicodeToUTF8(strUnicode, strUnicode.GetLength(), szBuffer, nCharacters);
		strUtf8.ReleaseBuffer(nCharacters);
		return nCharacters;
	}

	inline bool LoadUtf8FromUnicodeResource(HINSTANCE hInst, UINT nID, LCID lcid, CStringA& str) throw()
	{
		bool bSuccess = false;

		CStringW strUnicode;
		if (strUnicode.LoadString(hInst, nID, LANGIDFROMLCID(lcid)))
		{
			if (strUnicode.GetLength() == 0)
			{
				str = "";
				bSuccess = true;
			}
			else if (UnicodeToUtf8(strUnicode, str))
				bSuccess = true;
		}

		return bSuccess;
	}

	inline HRESULT GetUtf8SystemTime(LCID lcid, CStringA& strTime)
	{
		HRESULT hr = E_UNEXPECTED;
		SYSTEMTIME st = {0};
		GetSystemTime(&st);

		DATE date = 0;
		if (SystemTimeToVariantTime(&st, &date))
		{
			CComBSTR bstr;
			hr = VarBstrFromDate(date, lcid, 0, &bstr);
			if (SUCCEEDED(hr))
			{
				if (UnicodeToUtf8(static_cast<BSTR>(bstr), strTime))
					hr = S_OK;
				else
					hr = E_FAIL;
			}
		}
		return hr;
	}

}; // namespace VCUE

#endif // !defined(_VCUE_LOCALE_H___23343755_6CE2_4026_BE11_4488555CD8B3___INCLUDED_)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -