문제

(조금 업데이트되었습니다)

나는 PHP를 사용한 국제화에 그다지 경험이 없었으며, 검색의 거래는 내가 찾고 있던 답을 실제로 제공하지 않았다.

PHP를 사용하여 SMS 메시지를 보내기 위해 '관련'텍스트 만 유니 코드로 변환하는 신뢰할 수있는 방법을 사용해야합니다 (C#을 사용하여 서비스를 일시적으로 다시 작성하는 동안) - 분명히 현재 전송 된 메시지가 전송됩니다. 일반 텍스트로.

나는 모든 것을 유니 코드 숯으로 변환 할 수 있었지만 (표준 GSM Charset를 사용하는 것과는 달리) 모두 메시지는 160 대신 70 자로 제한됩니다.

그래서 내 진짜 질문은 다음과 같습니다. 메시지가 유니 코드로 인코딩되기위한 요구 사항을 감지하는 가장 신뢰할 수있는 방법은 무엇입니까? 절대적으로 필요 (예 : 라틴어가 아닌 문자의 경우)?

추가 정보 :

좋아, 그래서 나는 아침에 이것에 대해 일을 보냈는데, 나는 내가 시작했을 때보 다 더 이상 겨울을 보냈다 (확실히 숯불 변환과 관련하여 역량이 완전히 부족하기 때문에). 수정 된 시나리오는 다음과 같습니다.

외부 소스에서 나오는 텍스트 SMS 메시지가 있습니다.이 외부 소스는 일반 텍스트 + 유니 코드 슬래시 에스 케이블 문자로 나에게 응답을 제공합니다. 예를 들어 '표시된'텍스트 :

Öäü éàè א ין תמ십시오 כ십시오 בעבר십시오

보고:

u00f6 u00e4 u00fc u00e9 u00e0 u00e8 u05d0 u05d9 u05df u05ea u05de u05d9 u05db u05d4 u05d1 u05e2 u05d1 u05e2 u05u05d1 u05de.

이제 일반 텍스트, GSM 03.38 또는 유니 코드로 SMS 제공 업체에 보낼 수 있습니다. 분명히, 위의 위를 일반 텍스트로 보내면 많은 빠진 문자가 생성됩니다 (제공자가 공간으로 대체) - 콘텐츠가 무엇인지 관련하여 채택해야합니다. 내가 원하는 것 하다 이것으로 다음은 다음과 같습니다.

  1. 모든 텍스트 내에있는 경우 GSM 03.38 CodePage, as-is를 보내십시오. (위의 히브리어를 제외한 모든 것은이 범주에 적합하지만 변환해야합니다.)

  2. 그렇지 않으면 유니 코드로 변환하여 여러 메시지로 보내십시오 (유니 코드 한계는 SMS의 경우 160이 아닌 70 숯이므로).

위에서 말했듯이 PHP 에서이 작업을 수행하는 데 혼란 스러웠습니다 (C#은 간단한 전환 기능이 내장되어있어 많은 문제가되지 않았습니다). PHP에서 7 비트 인코딩에 대한 미리 만들어진 변환 클래스를 찾을 수 없었습니다. 문자열을 직접 변환하려는 시도는 쓸모없는 것처럼 보였습니다.

모든 도움은 대단히 감사하겠습니다.

도움이 되었습니까?

해결책

메커니즘에 들어가기 전에 개념적으로 다루기 위해,이 중 하나라도 명백한 경우, 문자열은 일련의 유니 코드 문자로 정의 될 수 있으며, 유니 코드는 모든 문자에 대한 코드 포인트로 알려진 ID 번호를 제공하는 데이터베이스입니다. 함께 일해야합니다. GSM-338에는 유니 코드 문자의 서브 세트가 포함되어 있으므로, 당신이하고있는 일은 문자열에서 코드 포인트 세트를 추출하고 해당 세트가 GSM-338에 포함되어 있는지 확인하는 것입니다.

// second column of http://unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT
$gsm338_codepoints = array(0x0040, 0x0000, ..., 0x00fc, 0x00e0)
$can_use_gsm338 = true;
foreach(codepoints($mystring) as $codepoint){
    if(!in_array($codepoint, $gsm338_codepoints)){
      $can_use_gsm338 = false;
      break;
    }
}

이는 PHP에 내장되지 않은 함수 코드 포인트 ($ string)의 정의를 남깁니다. PHP는 문자열이 일련의 유니 코드 문자가 아닌 일련의 바이트 시퀀스로 이해합니다. 간격을 연결하는 가장 좋은 방법은 현악기를 최대한 빨리 UTF8에 넣고 가능한 한 오랫동안 UTF8에 보관하는 것입니다. 외부 시스템을 처리 할 때 다른 인코딩을 사용해야하지만 전환을 분리해야합니다. 해당 시스템의 인터페이스 및 내부적으로 UTF8 만 처리하십시오.

UTF8의 PHP 문자열 사이에서 변환하는 데 필요한 기능과 코드 포인트 시퀀스를 찾을 수 있습니다. http://hsivonen.iki.fi/php-utf8/ 그래서 CodePoints () 함수입니다.

유니 코드 슬래시 에스 케이블 문자 ( "테스트 u00f6 u00e4 u00fc ...")를 제공하는 외부 소스에서 데이터를 가져 오면 해당 문자열 탈출 형식은 UTF8로 변환되어야합니다. 이 작업을 수행 할 함수를 모르는 모르겠습니다. 찾을 수없는 경우 문자열/regex 처리의 문제입니다. CodePoint 0xf6의 UTF8 표현과 함께.

다른 팁

이것은 오래된 실이지만 최근에 나는 최근에 매우 비슷한 문제를 해결해야했고 내 대답을 게시하고 싶었습니다. PHP 코드는 다소 간단합니다. 배열에서 GSM 유효한 문자 코드의 힘든 배열로 시작한 다음 현재 문자가 해당 배열에 있는지 확인하는 경우 간단히 확인합니다. Ord ($ string) 함수 통과 된 문자열의 첫 번째 문자의 ASCII 값을 반환합니다. 문자열이 GSM 가치가 있는지 확인하는 데 사용하는 코드는 다음과 같습니다.

    $valid_gsm_keycodes = Array(   
        0x0040, 0x0394, 0x0020, 0x0030, 0x00a1, 0x0050, 0x00bf, 0x0070,
        0x00a3, 0x005f, 0x0021, 0x0031, 0x0041, 0x0051, 0x0061, 0x0071,
        0x0024, 0x03a6, 0x0022, 0x0032, 0x0042, 0x0052, 0x0062, 0x0072,
        0x00a5, 0x0393, 0x0023, 0x0033, 0x0043, 0x0053, 0x0063, 0x0073,
        0x00e8, 0x039b, 0x00a4, 0x0034, 0x0035, 0x0044, 0x0054, 0x0064, 0x0074,
        0x00e9, 0x03a9, 0x0025, 0x0045, 0x0045, 0x0055, 0x0065, 0x0075,
        0x00f9, 0x03a0, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, 0x0076,
        0x00ec, 0x03a8, 0x0027, 0x0037, 0x0047, 0x0057, 0x0067, 0x0077, 
        0x00f2, 0x03a3, 0x0028, 0x0038, 0x0048, 0x0058, 0x0068, 0x0078,
        0x00c7, 0x0398, 0x0029, 0x0039, 0x0049, 0x0059, 0x0069, 0x0079,
        0x000a, 0x039e, 0x002a, 0x003a, 0x004a, 0x005a, 0x006a, 0x007a,
        0x00d8, 0x001b, 0x002b, 0x003b, 0x004b, 0x00c4, 0x006b, 0x00e4,
        0x00f8, 0x00c6, 0x002c, 0x003c, 0x004c, 0x00d6, 0x006c, 0x00f6,
        0x000d, 0x00e6, 0x002d, 0x003d, 0x004d, 0x00d1, 0x006d, 0x00f1,
        0x00c5, 0x00df, 0x002e, 0x003e, 0x004e, 0x00dc, 0x006e, 0x00fc,
        0x00e5, 0x00c9, 0x002f, 0x003f, 0x004f, 0x00a7, 0x006f, 0x00e0 );


        for($i = 0; $i < strlen($string); $i++) {
            if(!in_array($string[$i], $valid_gsm_keycodes)) return false;
        }

        return true;
function is_gsm0338( $utf8_string ) {
    $gsm0338 = array(
        '@','Δ',' ','0','¡','P','¿','p',
        '£','_','!','1','A','Q','a','q',
        '$','Φ','"','2','B','R','b','r',
        '¥','Γ','#','3','C','S','c','s',
        'è','Λ','¤','4','D','T','d','t',
        'é','Ω','%','5','E','U','e','u',
        'ù','Π','&','6','F','V','f','v',
        'ì','Ψ','\'','7','G','W','g','w',
        'ò','Σ','(','8','H','X','h','x',
        'Ç','Θ',')','9','I','Y','i','y',
        "\n",'Ξ','*',':','J','Z','j','z',
        'Ø',"\x1B",'+',';','K','Ä','k','ä',
        'ø','Æ',',','<','L','Ö','l','ö',
        "\r",'æ','-','=','M','Ñ','m','ñ',
        'Å','ß','.','>','N','Ü','n','ü',
        'å','É','/','?','O','§','o','à'
     );
    $len = mb_strlen( $utf8_string, 'UTF-8');

    for( $i=0; $i < $len; $i++)
        if (!in_array(mb_substr($utf8_string,$i,1,'UTF-8'), $gsm0338))
            return false;

    return true;
}

나는 이것이 PHP 코드가 아니라는 것을 알고 있지만 어쨌든 도움이 될 것이라고 생각합니다. 이것이 GSM 03.38로 보낼 수 있는지 감지하기 위해 쓴 앱에서 내가하는 방법입니다 (일반 텍스트와 비슷한 일을 할 수 있음). 그것은 일반적인 GSM 용으로, 하나는 확장 된 테이블의 번역 테이블을 가지고 있습니다. 그런 다음 모든 캐릭터를 통해 루프가 변환 할 수 있는지 확인하는 함수.

#define UCS2_TO_GSM_LOOKUP_TABLE_SIZE    0x100
#define NON_GSM                              0x80 
#define UCS2_GCL_RANGE                  24
#define UCS2_GREEK_CAPITAL_LETTER_ALPHA 0x0391
#define EXTEND                                0x001B
// note that the ` character is mapped to ' so that all characters that can be typed on
// a standard north american keyboard can be converted to the GSM default character set
static unsigned char  Ucs2ToGsm[UCS2_TO_GSM_LOOKUP_TABLE_SIZE] =
{           /*+0x0      +0x1        +0x2        +0x3        +0x4        +0x5        +0x6        +0x7*/
/*0x00*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x08*/    NON_GSM,    NON_GSM,    0x0a,       NON_GSM,    NON_GSM,    0x0d,       NON_GSM,    NON_GSM,
/*0x10*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x18*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x20*/    0x20,       0x21,       0x22,       0x23,       0x02,       0x25,       0x26,       0x27,
/*0x28*/    0x28,       0x29,       0x2a,       0x2b,       0x2c,       0x2d,       0x2e,       0x2f,
/*0x30*/    0x30,       0x31,       0x32,       0x33,       0x34,       0x35,       0x36,       0x37,
/*0x38*/    0x38,       0x39,       0x3a,       0x3b,       0x3c,       0x3d,       0x3e,       0x3f,
/*0x40*/    0x00,       0x41,       0x42,       0x43,       0x44,       0x45,       0x46,       0x47,
/*0x48*/    0x48,       0x49,       0x4a,       0x4b,       0x4c,       0x4d,       0x4e,       0x4f,
/*0x50*/    0x50,       0x51,       0x52,       0x53,       0x54,       0x55,       0x56,       0x57,
/*0x58*/    0x58,       0x59,       0x5a,       EXTEND,     EXTEND,     EXTEND,     EXTEND,     0x11,
/*0x60*/    0x27,       0x61,       0x62,       0x63,       0x64,       0x65,       0x66,       0x67,
/*0x68*/    0x68,       0x69,       0x6a,       0x6b,       0x6c,       0x6d,       0x6e,       0x6f,
/*0x70*/    0x70,       0x71,       0x72,       0x73,       0x74,       0x75,       0x76,       0x77,
/*0x78*/    0x78,       0x79,       0x7a,       EXTEND,     EXTEND,     EXTEND,     EXTEND,     NON_GSM,
/*0x80*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x88*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x90*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x98*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0xa0*/    NON_GSM,    0x40,       NON_GSM,    0x01,       0x24,       0x03,       NON_GSM,    0x5f,
/*0xa8*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0xb0*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0xb8*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x60,
/*0xc0*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x5b,       0x0e,       0x1c,       0x09,
/*0xc8*/    NON_GSM,    0x1f,       NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x60,
/*0xd0*/    NON_GSM,    0x5d,       NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x5c,       NON_GSM,
/*0xd8*/    0x0b,       NON_GSM,    NON_GSM,    NON_GSM,    0x5e,       NON_GSM,    NON_GSM,    0x1e,
/*0xe0*/    0x7f,       NON_GSM,    NON_GSM,    NON_GSM,    0x7b,       0x0f,       0x1d,       NON_GSM,
/*0xe8*/    0x04,       0x05,       NON_GSM,    NON_GSM,    0x07,       NON_GSM,    NON_GSM,    NON_GSM,
/*0xf0*/    NON_GSM,    0x7d,       0x08,       NON_GSM,    NON_GSM,    NON_GSM,    0x7c,       NON_GSM,
/*0xf8*/    0x0c,       0x06,       NON_GSM,    NON_GSM,    0x7e,       NON_GSM,    NON_GSM,    NON_GSM
};

static unsigned char Ucs2GclToGsm[UCS2_GCL_RANGE + 1] =
{
/*0x0391*/  0x41, // Alpha A
/*0x0392*/  0x42, // Beta B
/*0x0393*/  0x13, // Gamma
/*0x0394*/  0x10, // Delta
/*0x0395*/  0x45, // Epsilon E
/*0x0396*/  0x5A, // Zeta Z
/*0x0397*/  0x48, // Eta H
/*0x0398*/  0x19, // Theta
/*0x0399*/  0x49, // Iota I
/*0x039a*/  0x4B, // Kappa K
/*0x039b*/  0x14, // Lambda
/*0x039c*/  0x4D, // Mu M
/*0x039d*/  0x4E, // Nu N
/*0x039e*/  0x1A, // Xi
/*0x039f*/  0x4F, // Omicron O
/*0x03a0*/  0X16, // Pi
/*0x03a1*/  0x50, // Rho P
/*0x03a2*/  NON_GSM,
/*0x03a3*/  0x18, // Sigma
/*0x03a4*/  0x54, // Tau T
/*0x03a5*/  0x59, // Upsilon Y
/*0x03a6*/  0x12, // Phi 
/*0x03a7*/  0x58, // Chi X
/*0x03a8*/  0x17, // Psi
/*0x03a9*/  0x15  // Omega
};

bool Gsm0338Encoding::IsNotGSM( wchar_t szUnicodeChar )
{
    bool    result = true;
    if( szUnicodeChar < UCS2_TO_GSM_LOOKUP_TABLE_SIZE )
    {
        result = ( Ucs2ToGsm[szUnicodeChar] == NON_GSM );
    }
    else if( (szUnicodeChar >= UCS2_GREEK_CAPITAL_LETTER_ALPHA) &&
                (szUnicodeChar <= (UCS2_GREEK_CAPITAL_LETTER_ALPHA + UCS2_GCL_RANGE)) )
    {
        result = ( Ucs2GclToGsm[szUnicodeChar - UCS2_GREEK_CAPITAL_LETTER_ALPHA] == NON_GSM );
    }
    else if( szUnicodeChar == 0x20AC ) // €
    {
        result = false;
    }
    return result;
}

bool Gsm0338Encoding::IsGSM( const std::wstring& str )
{
    bool    result = true;
    if( std::find_if( str.begin(), str.end(), IsNotGSM ) != str.end() )
    {
        result = false;
    }
    return result;
}

PHP6은 더 나은 유니 코드 지원을받을 수 있지만 사용할 수있는 몇 가지 기능이 있습니다.

나의 첫 생각은 mb_convert_encoding 그러나 당신이 말했듯이 이것은 메시지를 70 숯으로 단축시킬 것입니다. 따라서 아마도 당신은 아마도 이것을 함께 사용할 수 있습니다. mb_detect_encoding?

보다: 멀티 바이트 기능

preg_match('/^[\x0A\x0C\x0D\x20-\x5F\x61-\x7E\xA0\xA1\xA3-\xA5\xA7'.
    '\xBF\xC4-\xC6\xC9\xD1\xD6\xD8\xDC\xDF\xE0\xE4-\xE9\xEC\xF1'.
    '\xF2\xF6\xF8\xF9\xFC'.
    json_decode('"\u0393\u0394\u0398\u039B\u039E\u03A0\u03A3\u03A6\u03A8\u03A9\u20AC"').
    ']*$/u', $text)

또는

preg_match('/^[\x0A\x0C\x0D\x20-\x5F\x61-\x7E\xA0\xA1\xA3-\xA5\xA7\xBF\xC4-\xC6\xC9\xD1\xD6\xD8\xDC\xDF\xE0\xE4-\xE9\xEC\xF1\xF2\xF6\xF8\xF9\xFCΓΔΘΛΞΠΣΦΨΩ€]*$/u', $text)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top