32

My application is localized in both English and Arabic.

Unfortunately, sometimes the autolayout behavior for localization is not required. By that, I mean reversing the leading and trailing spaces. I want to override this behavior. Is there any way to do that?

hbk
  • 10,908
  • 11
  • 91
  • 124
Abdalrahman Shatou
  • 4,550
  • 6
  • 50
  • 79

5 Answers5

42

To make leading act always as left (and trailing always like right), i.e. make it language independent, you can remove checkmark on "Respect language direction" on all constrains.

You can find this checkmark in constrain settings in the Attributes inspector under "First Item" button.

Respect language direction

Pavel
  • 920
  • 8
  • 16
24

The attributes leading and trailing are the same as left and right for left-to-right languages such as English, but in a right-to-left environment such as Hebrew or Arabic, leading and trailing are the same as right and left. When you create constraints, leading and trailing are the default values. You should usually use leading and trailing to make sure your interface is laid out appropriately in all languages, unless you’re making constraints that should remain the same regardless of language.

So, for your special cases, don't use leading and trailing, instead, explicitly use left and right when you create your constraints.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • 1
    Finally, an answer. Yes, I totally forgot about the left and right constraints – Abdalrahman Shatou Nov 15 '13 at 15:50
  • Tried it now and working as a charm! +1 for fast answer. I will give you the bounty after 19 hours ;) – Abdalrahman Shatou Nov 15 '13 at 15:53
  • Update: I reset the simulator and the defect returns back. The left constraints is translated into leading constraint. It seems that no way to fix this except not using auto-layout! – Abdalrahman Shatou Nov 15 '13 at 19:14
  • How are you creating the constraints? – Wain Nov 15 '13 at 20:23
  • Using IB. I control drag from the label to the superview and select Leading space. After reading your solution I tried the new constraints menu in Xcode 5 and select the left constraint and added the space I want and clicked "Add 1 Constraint". However, it translates into Leading constraint. I tried using another view at same level of the label and hence can use the Left constraint, but even then Xcode translates this left constraint to Leading one! Weird. – Abdalrahman Shatou Nov 16 '13 at 11:35
  • 1
    I'd look at adding the constraints in code where you can be 100% explicit. – Wain Nov 16 '13 at 12:42
  • 1
    IB doesn't necessarily offer all of the features available when you explicitly write the code. Think of IB as a convenience for simple constraints. – Wain Nov 23 '13 at 00:07
4

as in @Pavel answer, you should turn off 'Respect language direction' property. if you have lots of constraints, you can open xib or storyboard file in XML view and replace all 'leading' values with 'left' and all 'trailing' values with 'right' and you're done.

  • I did whole storyboard in two mins using this method just right click "Storyboard" then "Open As" and finally "Source Code". Then just do Search and Replace for "leading" -> "left" and "trailing" -> "right". Remember to do "Open As" then "Interface Builder" to view SB as normal. – Recycled Steel Aug 17 '16 at 13:29
2

Try this

  1. Create class for managing constraint in all views
@implementation RTLController

#pragma mark - Public

- (void)disableRTLForView:(UIView *)view
{
    [self updateSubviewForParentViewIfPossible:view];
}

#pragma mark - Private

- (void)updateConstraintForView:(UIView *)view
{
    NSMutableArray *constraintsToRemove = [[NSMutableArray alloc] init];
    NSMutableArray *constraintsToAdd = [[NSMutableArray alloc] init];

    for (NSLayoutConstraint *constraint in view.constraints) {

        NSLayoutAttribute firstAttribute = constraint.firstAttribute;
        NSLayoutAttribute secondAttribute = constraint.secondAttribute;

        if (constraint.firstAttribute == NSLayoutAttributeLeading) {
            firstAttribute = NSLayoutAttributeLeft;
        } else if (constraint.firstAttribute == NSLayoutAttributeTrailing) {
            firstAttribute = NSLayoutAttributeRight;
        }

        if (constraint.secondAttribute == NSLayoutAttributeLeading) {
            secondAttribute = NSLayoutAttributeLeft;
        } else if (constraint.secondAttribute == NSLayoutAttributeTrailing) {
            secondAttribute = NSLayoutAttributeRight;
        }

        NSLayoutConstraint *updatedConstraint = [self constraintWithFirstAttribute:firstAttribute secondAtribute:secondAttribute fromConstraint:constraint];
        [constraintsToRemove addObject:constraint];
        [constraintsToAdd addObject:updatedConstraint];

    }

    for (NSLayoutConstraint *constraint in constraintsToRemove) {
        [view removeConstraint:constraint];
    }
    for (NSLayoutConstraint *constraint in constraintsToAdd) {
        [view addConstraint:constraint];
    }
}

- (void)updateSubviewForParentViewIfPossible:(UIView *)mainView
{
    NSArray *subViews = mainView.subviews;
    [self updateConstraintForView:mainView];

    if (subViews.count) {
        for (UIView * subView in subViews) {
            [self updateConstraintForView:subView];
            [self updateSubviewForParentViewIfPossible:subView];
        }
    }
}

- (NSLayoutConstraint *)constraintWithFirstAttribute:(NSLayoutAttribute)firstAttribute secondAtribute:(NSLayoutAttribute)secondAttribute fromConstraint:(NSLayoutConstraint *)originalConstraint
{
    NSLayoutConstraint *updatedConstraint =
    [NSLayoutConstraint constraintWithItem:originalConstraint.firstItem
                                 attribute:firstAttribute
                                 relatedBy:originalConstraint.relation
                                    toItem:originalConstraint.secondItem
                                 attribute:secondAttribute
                                multiplier:originalConstraint.multiplier
                                  constant:originalConstraint.constant];
    return updatedConstraint;
}
@end
  1. Add this code in to controller that should disable RTL behavior
RTLController *rtl = [[RTLController alloc] init];
[rtl disableRTLForView:self.view];
hbk
  • 10,908
  • 11
  • 91
  • 124
  • This is great, i use it just for RTL languages on iOS8. For iOS9 and higher I use the full layout update the system provide. – Pichirichi Jan 12 '16 at 08:04
1

another easy way

Select any view from the storyboard

from the attributes inspector on the right select set "Semantic" to "Force Left-to-Right"

Somebody
  • 703
  • 1
  • 7
  • 23