Жирний і нежирний текст в єдиному UILabel?


254

Як можна було б включити жирний і нежирний текст у uiLabel?

Я б краще не користувався UIWebView .. Я також читав, що це можливо, використовуючи NSAttributedString, але я не маю уявлення, як це використовувати. Будь-які ідеї?

Apple досягає цього в кількох своїх програмах; Скріншоттекст посилання

Дякую! - Дом


Перегляньте цю тему з попереднього переповнення стека. (В основному, створіть два UILabel і розташуйте їх правильно відносно один одного.)
samkass

Відповіді:


360

Оновлення

У Swift нам не доводиться мати справу зі старими речами iOS5, крім синтаксису коротше, тому все стає дуже просто:

Швидкий 5

func attributedString(from string: String, nonBoldRange: NSRange?) -> NSAttributedString {
    let fontSize = UIFont.systemFontSize
    let attrs = [
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: fontSize),
        NSAttributedString.Key.foregroundColor: UIColor.black
    ]
    let nonBoldAttribute = [
        NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize),
    ]
    let attrStr = NSMutableAttributedString(string: string, attributes: attrs)
    if let range = nonBoldRange {
        attrStr.setAttributes(nonBoldAttribute, range: range)
    }
    return attrStr
}

Швидкий 3

func attributedString(from string: String, nonBoldRange: NSRange?) -> NSAttributedString {
    let fontSize = UIFont.systemFontSize
    let attrs = [
        NSFontAttributeName: UIFont.boldSystemFont(ofSize: fontSize),
        NSForegroundColorAttributeName: UIColor.black
    ]
    let nonBoldAttribute = [
        NSFontAttributeName: UIFont.systemFont(ofSize: fontSize),
    ]
    let attrStr = NSMutableAttributedString(string: string, attributes: attrs)
    if let range = nonBoldRange {
        attrStr.setAttributes(nonBoldAttribute, range: range)
    }
    return attrStr
}

Використання:

let targetString = "Updated 2012/10/14 21:59 PM"
let range = NSMakeRange(7, 12)

let label = UILabel(frame: CGRect(x:0, y:0, width:350, height:44))
label.backgroundColor = UIColor.white
label.attributedText = attributedString(from: targetString, nonBoldRange: range)
label.sizeToFit()

Бонус: Інтернаціоналізація

Деякі люди коментували інтернаціоналізацію. Я особисто думаю, що це питання не входить до сфери цього питання, але для навчальних цілей я б це зробив

// Date we want to show
let date = Date()

// Create the string.
// I don't set the locale because the default locale of the formatter is `NSLocale.current` so it's good for internationalisation :p
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let targetString = String(format: NSLocalizedString("Update %@", comment: "Updated string format"),
                          formatter.string(from: date))

// Find the range of the non-bold part
formatter.timeStyle = .none
let nonBoldRange = targetString.range(of: formatter.string(from: date))

// Convert Range<Int> into NSRange
let nonBoldNSRange: NSRange? = nonBoldRange == nil ?
    nil :
    NSMakeRange(targetString.distance(from: targetString.startIndex, to: nonBoldRange!.lowerBound),
                targetString.distance(from: nonBoldRange!.lowerBound, to: nonBoldRange!.upperBound))

// Now just build the attributed string as before :)
label.attributedText = attributedString(from: targetString,
                                        nonBoldRange: nonBoldNSRange)

Результат (припускаючи, що англійська та японська мови Localizable.strings доступні)

введіть тут опис зображення

введіть тут опис зображення


Попередня відповідь для iOS6 та пізнішої версії (Objective-C все ще працює):

У iOS6 UILabel, UIButton, UITextView, UITextField, підтримка приписувала рядки , які означають , що ми не повинні створювати CATextLayerS в якості нашого одержувача для приписуваних рядків. Крім того, щоб зробити атрибутивний рядок, нам більше не потрібно грати з CoreText :) У нас є нові класи в подібному об'-c Foundation.framework NSParagraphStyleта інших константах, які полегшать наше життя. Так!

Отже, якщо у нас є цей рядок:

NSString *text = @"Updated: 2012/10/14 21:59"

Нам потрібно лише створити атрибутовану рядок:

if ([_label respondsToSelector:@selector(setAttributedText:)])
{
    // iOS6 and above : Use NSAttributedStrings

    // Create the attributes
    const CGFloat fontSize = 13;
    NSDictionary *attrs = @{
        NSFontAttributeName:[UIFont boldSystemFontOfSize:fontSize],
        NSForegroundColorAttributeName:[UIColor whiteColor]
    };
    NSDictionary *subAttrs = @{
        NSFontAttributeName:[UIFont systemFontOfSize:fontSize]
    };

    // Range of " 2012/10/14 " is (8,12). Ideally it shouldn't be hardcoded
    // This example is about attributed strings in one label
    // not about internationalisation, so we keep it simple :)
    // For internationalisation example see above code in swift
    const NSRange range = NSMakeRange(8,12);

    // Create the attributed string (text + attributes)
    NSMutableAttributedString *attributedText =
      [[NSMutableAttributedString alloc] initWithString:text
                                             attributes:attrs];
    [attributedText setAttributes:subAttrs range:range];

    // Set it in our UILabel and we are done!
    [_label setAttributedText:attributedText];
} else {
    // iOS5 and below
    // Here we have some options too. The first one is to do something
    // less fancy and show it just as plain text without attributes.
    // The second is to use CoreText and get similar results with a bit
    // more of code. Interested people please look down the old answer.

    // Now I am just being lazy so :p
    [_label setText:text];
}

Існує кілька хороших вступних повідомлень в блозі тут з хлопців в invasivecode , пояснюють з великою кількістю прикладів використання NSAttributedString, зверніть увагу на «Введення в NSAttributedString для IOS 6» і «приписували рядків для прошивкою з допомогою Interface Builder» :)

PS: Над кодом він повинен працювати, але він був складений мозком. Сподіваюся, що достатньо :)


Старий відповідь для iOS5 та нижче

Використовуйте CATextLayer з NSAttributedString! набагато легше і простіше, ніж 2 UILabels. (iOS 3.2 і вище)

Приклад.

Не забудьте додати рамки QuartzCore (потрібні для CALayers) та CoreText (необхідні для атрибутизованого рядка.)

#import <QuartzCore/QuartzCore.h>
#import <CoreText/CoreText.h>

Нижче приклад додасть підшар на панель інструментів навігаційного контролера. à la Mail.app в iPhone. :)

- (void)setRefreshDate:(NSDate *)aDate
{
    [aDate retain];
    [refreshDate release];
    refreshDate = aDate;

    if (refreshDate) {

        /* Create the text for the text layer*/    
        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"MM/dd/yyyy hh:mm"];

        NSString *dateString = [df stringFromDate:refreshDate];
        NSString *prefix = NSLocalizedString(@"Updated", nil);
        NSString *text = [NSString stringWithFormat:@"%@: %@",prefix, dateString];
        [df release];

        /* Create the text layer on demand */
        if (!_textLayer) {
            _textLayer = [[CATextLayer alloc] init];
            //_textLayer.font = [UIFont boldSystemFontOfSize:13].fontName; // not needed since `string` property will be an NSAttributedString
            _textLayer.backgroundColor = [UIColor clearColor].CGColor;
            _textLayer.wrapped = NO;
            CALayer *layer = self.navigationController.toolbar.layer; //self is a view controller contained by a navigation controller
            _textLayer.frame = CGRectMake((layer.bounds.size.width-180)/2 + 10, (layer.bounds.size.height-30)/2 + 10, 180, 30);
            _textLayer.contentsScale = [[UIScreen mainScreen] scale]; // looks nice in retina displays too :)
            _textLayer.alignmentMode = kCAAlignmentCenter;
            [layer addSublayer:_textLayer];
        }

        /* Create the attributes (for the attributed string) */
        CGFloat fontSize = 13;
        UIFont *boldFont = [UIFont boldSystemFontOfSize:fontSize];
        CTFontRef ctBoldFont = CTFontCreateWithName((CFStringRef)boldFont.fontName, boldFont.pointSize, NULL);
        UIFont *font = [UIFont systemFontOfSize:13];
        CTFontRef ctFont = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize, NULL);
        CGColorRef cgColor = [UIColor whiteColor].CGColor;
        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (id)ctBoldFont, (id)kCTFontAttributeName,
                                    cgColor, (id)kCTForegroundColorAttributeName, nil];
        CFRelease(ctBoldFont);
        NSDictionary *subAttributes = [NSDictionary dictionaryWithObjectsAndKeys:(id)ctFont, (id)kCTFontAttributeName, nil];
        CFRelease(ctFont);

        /* Create the attributed string (text + attributes) */
        NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:text attributes:attributes];
        [attrStr addAttributes:subAttributes range:NSMakeRange(prefix.length, 12)]; //12 is the length of " MM/dd/yyyy/ "

        /* Set the attributes string in the text layer :) */
        _textLayer.string = attrStr;
        [attrStr release];

        _textLayer.opacity = 1.0;
    } else {
        _textLayer.opacity = 0.0;
        _textLayer.string = nil;
    }
}

У цьому прикладі у мене є лише два різних типи шрифту (жирний та звичайний), але ви також можете мати різний розмір шрифту, різний колір, курсив, підкреслений тощо. Погляньте на атрибути NSAttributedString / NSMutableAttributedString та CoreText атрибути .

Сподіваюся, це допомагає


2
На жаль, це (та інші відповіді) не є інтернаціоналізацією. Підтримка тегів Html (<b>, <i>), як на Android, була б чудовою.
Віктор Г

1
Оскільки це приклад, я вважав за краще не займатися цією справою. Якщо вам потрібна локалізація, ви можете отримати компонент дати від NSDate і знайти програмно відповідний жирний / нежирний діапазон (замість жорсткого кодування діапазонів. У коді вище є коментарі, в яких згадується, що жорстке кодування не є ідеальним)
nacho4d

1
Вам слід подумати про використання у своєму коді більш читаних літератур Objective-C. Наприклад [NSDictionary dictionaryWithObjectsAndKeys: boldFont, NSFontAttributeName, foregroundColor, NSForegroundColorAttributeName, nil]стає @{ NSFontAttributeName: boldFont, NSForegroundColorAttributeName: foregroundColor }.
PatrickNLT

@ nacho4d Чудово! Але є помилка друку: синтаксис вимагає фігурних дужок ( {), а не квадратних дужок ( [).
PatrickNLT

Я додав якийсь код, який показує інтернаціоналізаторський підхід
nacho4d

85

Спробуйте категорію на UILabel:

Ось як це використовується:

myLabel.text = @"Updated: 2012/10/14 21:59 PM";
[myLabel boldSubstring: @"Updated:"];
[myLabel boldSubstring: @"21:59 PM"];

І ось категорія

UILabel + Boldify.h

- (void) boldSubstring: (NSString*) substring;
- (void) boldRange: (NSRange) range;

UILabel + Boldify.m

- (void) boldRange: (NSRange) range {
    if (![self respondsToSelector:@selector(setAttributedText:)]) {
        return;
    }
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
    [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range];

    self.attributedText = attributedText;    
}

- (void) boldSubstring: (NSString*) substring {
    NSRange range = [self.text rangeOfString:substring];
    [self boldRange:range];
}

Зауважте, що це працюватиме лише в iOS 6 та новіших версіях. Він буде просто проігнорований в iOS 5 і раніше.


2
Хороша категорія. Хоча це не зробить шрифт жирним. Для того, щоб це зробити, ви мусили зробити це таким: @{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]}я виступив з пропозицією
Lonkly

1
Якщо шрифт вашої етикетки не є системним шрифтом, то вам потрібно змінити: [UIFont boldSystemFontOfSize:self.font.pointSize]TO[UIFont fontWithName:self.font.fontName size:self.font.pointSize]
лій

48

Це легко зробити в Interface Builder :

1) зробити UILabel віднесено до інспектора атрибутів

Сміливий приклад Крок 1

2) виберіть частину фрази, яку ви хочете зробити жирним

Сміливий приклад Крок 2

3) змінити свій шрифт (або жирний шрифт того ж шрифту) у селекторі шрифту

Сміливий приклад Крок 3

Це все!


Схоже, ви можете це зробити лише для жирних шрифтів (та інших типів шрифту), а не для застосування інших атрибутів, таких як підкреслення? (навіть незважаючи на те, що в засобі вибору шрифту є підкреслення, підкреслено для мене сірим) Ви бачите таку саму поведінку?
pj4533

2
схоже, це добре для статичного тексту, я все одно не знаю цього, перш ніж читати цю публікацію.
преетам

Моя стурбованість цією новою функцією Builder інтерфейсів полягає в тому, що ви змушені вибирати певний спеціальний шрифт, а не системний шрифт, таким чином, ви пропустите всю реалізацію системи для людей з обмеженими оглядами / доступності?
Літоме

1
Я зробив частину свого тексту жирним, і це показує, як це повинно бути в інспекторі атрибутів, але не в тренажері або навіть у розгортці.
Бесат

45

Існує категорія, заснована на категорії bbrame. Це працює аналогічно, але дозволяє зміцнювати одне і те ж UILabelкілька разів із кумулятивними результатами.

UILabel + Boldify.h

@interface UILabel (Boldify)
- (void) boldSubstring: (NSString*) substring;
- (void) boldRange: (NSRange) range;
@end

UILabel + Boldify.m

@implementation UILabel (Boldify)
- (void)boldRange:(NSRange)range {
    if (![self respondsToSelector:@selector(setAttributedText:)]) {
        return;
    }
    NSMutableAttributedString *attributedText;
    if (!self.attributedText) {
        attributedText = [[NSMutableAttributedString alloc] initWithString:self.text];
    } else {
        attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
    }
    [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range];
    self.attributedText = attributedText;
}

- (void)boldSubstring:(NSString*)substring {
    NSRange range = [self.text rangeOfString:substring];
    [self boldRange:range];
}
@end

За допомогою цих виправлень ви можете використовувати його кілька разів, наприклад:

myLabel.text = @"Updated: 2012/10/14 21:59 PM";
[myLabel boldSubstring: @"Updated:"];
[myLabel boldSubstring: @"21:59 PM"];

матиме результат: " Оновлено: 14.10.2012 21:59 ".


Божевільно, він буде жирним лише останню підрядку, тобто лише 21:59.
Prajeet Shrestha

Я перевірив це рік тому і, здавалося, працював у той час. Вся справа в моєму дописі полягала в тому, щоб змінити категорію bbrame для обробки декількох шрифтів. Наразі я не можу цього зробити, але через два тижні я повторно випробую цей код, щоб переконатися, що він працює.
Божевільний йогурт

Божевільна перевірка моєї відповіді нижче пл. І, будь ласка, підкажіть, як зробити його багаторазовим.
Prajeet Shrestha

27

Це працювало для мене:

CGFloat boldTextFontSize = 17.0f;

myLabel.text = [NSString stringWithFormat:@"%@ 2012/10/14 %@",@"Updated:",@"21:59 PM"];

NSRange range1 = [myLabel.text rangeOfString:@"Updated:"];
NSRange range2 = [myLabel.text rangeOfString:@"21:59 PM"];

NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:myLabel.text];

[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]}
                        range:range1];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]}
                        range:range2];

myLabel.attributedText = attributedText;

Для версії Swift: Дивіться тут


красиво і просто! Дякую!
Мона

25

Я прийняв відповідь Божевільного йогурту на швидкі розширення.

extension UILabel {

    func boldRange(_ range: Range<String.Index>) {
        if let text = self.attributedText {
            let attr = NSMutableAttributedString(attributedString: text)
            let start = text.string.characters.distance(from: text.string.startIndex, to: range.lowerBound)
            let length = text.string.characters.distance(from: range.lowerBound, to: range.upperBound)
            attr.addAttributes([NSFontAttributeName: UIFont.boldSystemFont(ofSize: self.font.pointSize)], range: NSMakeRange(start, length))
            self.attributedText = attr
        }
    }

    func boldSubstring(_ substr: String) {
        if let text = self.attributedText {
            var range = text.string.range(of: substr)
            let attr = NSMutableAttributedString(attributedString: text)
            while range != nil {
                let start = text.string.characters.distance(from: text.string.startIndex, to: range!.lowerBound)
                let length = text.string.characters.distance(from: range!.lowerBound, to: range!.upperBound)
                var nsRange = NSMakeRange(start, length)
                let font = attr.attribute(NSFontAttributeName, at: start, effectiveRange: &nsRange) as! UIFont
                if !font.fontDescriptor.symbolicTraits.contains(.traitBold) {
                    break
                }
                range = text.string.range(of: substr, options: NSString.CompareOptions.literal, range: range!.upperBound..<text.string.endIndex, locale: nil)
            }
            if let r = range {
                boldRange(r)
            }
        }
    }
}

Можливо, не дуже хороша конверсія між діапазоном і NSRange, але я не знайшов чогось кращого.


1
Велике спасибі! Саме те, що мені було потрібно! Я змінив другий рядок в boldSubstring(_:)для , var range = text.string.range(of: substr, options: .caseInsensitive)щоб зробити рядки з різною капіталізацією також виділена жирним шрифтом.
fl034

21

Перевірте TTTAttributedLabel . Це замінна версія для UILabel, яка дозволяє змішати шрифт та кольори в одній мітці, встановивши NSAttributedString як текст для цієї мітки.


5
Я повинен погодитися з використанням краплі в заміні (є кілька навколо). Apple просто ще не закінчила роботу над цим матеріалом. За винятком академічних занять, я не думаю, що це дійсно варто намагатися зрозуміти та впровадити цей безлад - це, мабуть, все буде добре прибрано у наступному випуску (чи так). :) github.com/AliSoftware/OHAttributedLabel
ловець

@trapper - ти врятував мій день за цим посиланням ... +1000!
Качка

Я також рекомендую OHAttributedLabel. Ви можете використовувати теги HTML, як <b> і <u> (та інші) прямо в рядку.
RyanG

12

У цьому випадку ви можете спробувати,

UILabel *displayLabel = [[UILabel alloc] initWithFrame:/*label frame*/];
displayLabel.font = [UIFont boldSystemFontOfSize:/*bold font size*/];

NSMutableAttributedString *notifyingStr = [[NSMutableAttributedString alloc] initWithString:@"Updated: 2012/10/14 21:59 PM"];
[notifyingStr beginEditing];
[notifyingStr addAttribute:NSFontAttributeName
                     value:[UIFont systemFontOfSize:/*normal font size*/]
                     range:NSMakeRange(8,10)/*range of normal string, e.g. 2012/10/14*/];
[notifyingStr endEditing];

displayLabel.attributedText = notifyingStr; // or [displayLabel setAttributedText: notifyingStr];

PS Присвоїти значення до мітці першої (наприклад , displayLabel.text = @ "Оновлене: 2013/12/23 21:59 PM";)
Мазен Кассер

8

Щоб зробити текст жирним, а також підкреслити у UILabel. Просто додайте наступні рядки у свій код.

NSRange range1 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_terms", @"")];
NSRange range2 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_policy", @"")];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:lblTermsAndCondition.text];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]}
                        range:range1];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]}
                        range:range2];


[attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName
                  value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
                  range:range1];

[attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName
                       value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
                       range:range2];



lblTermsAndCondition.attributedText = attributedText;

5

Скористайтеся наведеним нижче кодом. Я сподіваюся, що це допоможе вам.

NSString *needToChangeStr=@"BOOK";
NSString *display_string=[NSString stringWithFormat:@"This is %@",book];

NSMutableAttributedString *attri_str=[[NSMutableAttributedString alloc]initWithString:display_string];

int begin=[display_string length]-[needToChangeStr length];
int end=[needToChangeStr length];


[attri_str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue-Bold" size:30] range:NSMakeRange(begin, end)];

4

Швидкий 4:

// attribute with color red and Bold
var attrs1 = [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 20), NSAttributedStringKey.foregroundColor: UIColor.red]

// attribute with color black and Non Bold
var attrs2 = [NSAttributedStringKey.font: UIFont(name: "Roboto-Regular", size: 20), NSAttributedStringKey.foregroundColor: UIColor.black]  

var color1 = NSAttributedString(string: "RED", attributes: attrs1)

var color2 = NSAttributedString(string: " BLACK", attributes: attrs2)

var string = NSMutableAttributedString()

string.append(color1)

string.append(color2)

// print the text with **RED** BLACK
print("Final String : \(string)")

3

Сподіваюся, що ця відповість вашим потребам. Введіть рядок для обробки як введення та введіть слова, які повинні бути жирними / кольоровими як введення.

func attributedString(parentString:String, arrayOfStringToProcess:[String], color:UIColor) -> NSAttributedString
{
    let parentAttributedString = NSMutableAttributedString(string:parentString, attributes:nil)
    let parentStringWords = parentAttributedString.string.components(separatedBy: " ")
    if parentStringWords.count != 0
    {
        let wordSearchArray = arrayOfStringToProcess.filter { inputArrayIndex in
            parentStringWords.contains(where: { $0 == inputArrayIndex }
            )}
        for eachWord in wordSearchArray
        {
            parentString.enumerateSubstrings(in: parentString.startIndex..<parentString.endIndex, options: .byWords)
            {
                (substring, substringRange, _, _) in
                if substring == eachWord
                {
                    parentAttributedString.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 15), range: NSRange(substringRange, in: parentString))
                    parentAttributedString.addAttribute(.foregroundColor, value: color, range: NSRange(substringRange, in: parentString))
                }
            }
        }
    }
    return parentAttributedString
}

Дякую. Щасливе кодування.


2

Немає потреби в NSRange із наступним кодом, який я щойно реалізував у своєму проекті (у Swift):

    //Code sets label (yourLabel)'s text to "Tap and hold(BOLD) button to start recording."
    let boldAttribute = [
        //You can add as many attributes as you want here.
        NSFontAttributeName: UIFont(name: "HelveticaNeue-Bold", size: 18.0)!]

    let regularAttribute = [
        NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!]

    let beginningAttributedString = NSAttributedString(string: "Tap and ", attributes: regularAttribute )
    let boldAttributedString = NSAttributedString(string: "hold ", attributes: boldAttribute)
    let endAttributedString = NSAttributedString(string: "button to start recording.", attributes: regularAttribute )
    let fullString =  NSMutableAttributedString()

    fullString.appendAttributedString(beginningAttributedString)
    fullString.appendAttributedString(boldAttributedString)
    fullString.appendAttributedString(endAttributedString)

    yourLabel.attributedText = fullString

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.